From 3bbfbf7940e745fc944fc9503ffb3241848aa265 Mon Sep 17 00:00:00 2001 From: Mathieu Serandour Date: Sat, 11 Dec 2021 15:48:21 +0100 Subject: [PATCH] terminal uses a timer --- kernel/drivers/terminal/terminal.c | 141 ++++++++++++++++++++++------- kernel/drivers/terminal/terminal.h | 10 +- kernel/drivers/terminal/video.c | 9 +- kernel/entry.c | 9 +- 4 files changed, 122 insertions(+), 47 deletions(-) diff --git a/kernel/drivers/terminal/terminal.c b/kernel/drivers/terminal/terminal.c index 2c59aae..a7d364e 100644 --- a/kernel/drivers/terminal/terminal.c +++ b/kernel/drivers/terminal/terminal.c @@ -1,5 +1,6 @@ #include #include +#include #include "terminal.h" #include "video.h" @@ -8,6 +9,8 @@ #include "../../lib/assert.h" #include "../../lib/logging.h" #include "../../memory/heap.h" +#include "../../int/apic.h" +#include "../../int/idt.h" #define TAB_SPACE 6 @@ -32,7 +35,7 @@ static terminal_handler_t terminal_handler = NULL; static bool need_refresh = false; -void default_terminal_handler(const char* s, size_t l) { +void empty_terminal_handler(const char* s, size_t l) { (void) (s + l); // empty handler by default, // make sure not to execute the address 0 :) @@ -42,6 +45,9 @@ void default_terminal_handler(const char* s, size_t l) { #define TERMINAL_LINES_MAX 75 +static void append_string(const char *string, size_t length); + + static Image* charmap = NULL; static struct Char* char_buffer = NULL; @@ -56,26 +62,52 @@ static uint32_t current_bgcolor = 0; static unsigned margin_left, margin_top; +#define UPDATE_PERIOD_MS (1000 / 60) + + +// "uint8_t" but designates a binary file +extern uint8_t _binary_charmap_bmp; + + +static unsigned timerID = INVALID_TIMER_ID; + + + +static char* stream_buffer = NULL; + +static unsigned stream_buffer_size = 0; +static volatile unsigned stream_buffer_content_size = 0; + + +// should be called every UPDATE_PERIOD ms +// should execute in an IRQ +void terminal_update(void) { + static unsigned update_cur_line = 0; + + + stream_buffer_content_size = 0; + + + if(need_refresh) { + need_refresh = 0; + flush_screen(); + } + // flush the buffer +} -// "int" but designates a binary file -extern int _binary_charmap_bmp; +void terminal_remove(void) { + apic_delete_timer(timerID); +} -void setup_terminal(void) { - log_debug("setup the terminal..."); +void terminal_install_early(void) { + log_debug("install the terminal..."); assert(charmap == NULL); assert(char_buffer == NULL); - - charmap = loadBMP_24b_1b(&_binary_charmap_bmp); - assert(charmap != NULL); - assert(charmap->bpp == 1); - assert(charmap->pitch == 1); - assert(charmap->w == TERMINAL_CHARMAP_W); - assert(charmap->h == TERMINAL_CHARMAP_H); const Image* screenImage = getScreenImage(); @@ -105,12 +137,27 @@ void setup_terminal(void) { margin_top = (screenImage->h - term_nlines * TERMINAL_FONTHEIGHT) / 2; #endif + stream_buffer = malloc(ncols * term_nlines); + + set_terminal_handler(empty_terminal_handler); +} + +// finish intallation when memory +// is well initialized +void terminal_install_late(void) { + timerID = apic_create_timer(terminal_update, UPDATE_PERIOD_MS); + charmap = loadBMP_24b_1b(&_binary_charmap_bmp); + + set_terminal_handler(write_string); + + terminal_clear(); } void terminal_clear(void) { + cur_col = 0; cur_line = 0; first_line = 0; @@ -122,6 +169,7 @@ void terminal_clear(void) { *(ptr++) = make_Char(0); flush_screen(); + } @@ -147,6 +195,11 @@ static void move_buffer(int lines) { size_t buff_size = nlines * ncols; memmove(char_buffer, char_buffer + bytes, sizeof(struct Char)*(buff_size - bytes)); + + // cannot touch the first one: it is already written + for(unsigned i = 1; i < bytes; i++) { + char_buffer[i+buff_size-bytes] = make_Char(0); + } } } @@ -174,23 +227,29 @@ static struct Char make_Char(char c) { } -// emplace the char in the buffer, dosn't draw anything +static void emplace_normal_char(char c) { + char_buffer[ncols * cur_line + cur_col] = make_Char(c); + + struct Char* ch = &char_buffer[ncols * cur_line + cur_col]; + + + if(cur_col >= ncols) + next_line(); + + if(!need_refresh) + print_char(ch, cur_line - first_line, cur_col); + + + cur_col += 1; +} + + +// emplace the char in the buffer, and maybe draw static void emplace_char(char c) { switch(c) { - // any character default: - - char_buffer[ncols * cur_line + cur_col] = make_Char(c); - - struct Char* ch = &char_buffer[ncols * cur_line + cur_col]; - - cur_col += 1; - if(!need_refresh) - print_char(ch, cur_line - first_line, cur_col); - - if(cur_col >= ncols) - next_line(); - + // any character + emplace_normal_char(c); break; case '\n': @@ -198,8 +257,7 @@ static void emplace_char(char c) { for(unsigned i=cur_col;i < ncols; i++) { //print_char(ch, cur_line - first_line, cur_col); - emplace_char(' '); - + emplace_normal_char(' '); } } break; @@ -211,10 +269,7 @@ static void emplace_char(char c) { emplace_char(' '); } - - //if(cur_col >= ncols) break; - case '\r': cur_col = 0; break; @@ -284,9 +339,25 @@ static void flush_screen(void) { } -static void write_string(const char *string, size_t length) { - need_refresh = false; +// add the string to the buffer +static void append_string(const char *string, size_t length) { +// atomic operation + _cli(); + + memcpy(stream_buffer + stream_buffer_content_size, + string, + length); + + stream_buffer_content_size += length; + + _sti(); +} + + + +static void write_string(const char *string, size_t length) { + //need_refresh = false; for(;length>0;--length) { char c = *string++; @@ -296,8 +367,8 @@ static void write_string(const char *string, size_t length) { emplace_char(c); } - if(need_refresh) - flush_screen(); + //if(need_refresh) + // flush_screen(); } diff --git a/kernel/drivers/terminal/terminal.h b/kernel/drivers/terminal/terminal.h index 2e838ea..82e15ec 100644 --- a/kernel/drivers/terminal/terminal.h +++ b/kernel/drivers/terminal/terminal.h @@ -33,7 +33,11 @@ terminal_handler_t get_terminal_handler(void); // setup_function void assert_terminal(void); -void setup_terminal(void); +void terminal_install_early(void); +void terminal_install_late (void); +void terminal_remove(void); +void terminal_update(void); + void terminal_clear(void); // change the default terminal handler, @@ -49,4 +53,6 @@ void set_terminal_handler(terminal_handler_t h); void set_terminal_bgcolor(uint32_t c); void set_terminal_fgcolor(uint32_t c); -void terminal_set_colors(uint32_t foreground, uint32_t background); \ No newline at end of file +void terminal_set_colors(uint32_t foreground, uint32_t background); + + diff --git a/kernel/drivers/terminal/video.c b/kernel/drivers/terminal/video.c index a1ac26e..bc6c6ea 100644 --- a/kernel/drivers/terminal/video.c +++ b/kernel/drivers/terminal/video.c @@ -309,8 +309,6 @@ const Image* getScreenImage(void) { return &screen; } - -extern uint8_t __image_pix; /* // assert that the checks are already performed static Image* loadBMP_24(const struct BMPFileHeader* restrict header, const void* restrict body) { @@ -563,13 +561,13 @@ Image* loadBMP_24b_1b(const void* rawFile) { const uint8_t* srcpix = (const uint8_t *)header + header->body_offset; - + uint32_t pitch = (w+7)/8; loadBMP_24b_1b_ret.w = w; loadBMP_24b_1b_ret.h = h; loadBMP_24b_1b_ret.bpp = 1; - loadBMP_24b_1b_ret.pitch = ((w+7) / 8); - loadBMP_24b_1b_ret.pix = &__image_pix; + loadBMP_24b_1b_ret.pitch = pitch; + loadBMP_24b_1b_ret.pix = malloc(pitch * h); assert(loadBMP_24b_1b_ret.pitch == 1); assert(w == 6); @@ -588,7 +586,6 @@ Image* loadBMP_24b_1b(const void* rawFile) { // put 1 iif r channel > 128 byte |= *(src_ptr) >> 7; - //if((x % 8 == 0 && x != 0) || x == w-1) { if(x == w-1) { diff --git a/kernel/entry.c b/kernel/entry.c index aa6490e..7793f18 100644 --- a/kernel/entry.c +++ b/kernel/entry.c @@ -184,10 +184,12 @@ void _start(struct stivale2_struct *stivale2_struct) { // so we need to load our gdt after our // terminal is successfully installed - setup_terminal(); - append_paging_initialization(); + terminal_install_early(); terminal_set_colors(0xfff0a0, 0x212121); - terminal_clear(); + + append_paging_initialization(); + + terminal_install_late(); puts(&_binary_bootmessage_txt); @@ -213,7 +215,6 @@ void _start(struct stivale2_struct *stivale2_struct) { for(;;) { asm volatile("hlt"); - printf("%lu\r", clock()); } __builtin_unreachable();