Optimize screen & serial output handling. (#85)

- Enable VGA/FB to output box drawing characters while maintaining VT100
   character set for serial. Shorten and simplify the screen setup code.

 - Track the background color to decide if the serial output needs to be
   inverted. Remove no longer needed logic for known areas of the screen that
   need to be inverted. As a bonus - popup menu can now be also inverted on
   serial.

 - Reduce the amount of data sent to serial by using CR+LF when possible
   instead of always relying on absolute positioning. Add tty_print()
   for positioning the cursor, remove no longer needed tty_print().

 - Remove no longer needed "LF -> LF+CR" logic from serial_echo_print().

Before (gcc-11.3.0-x86_64):
      text       data        bss      total filename
       929        357         64       1350 system/serial.o
      3517       1356         54       4927 app/display.o

After (gcc-11.3.0-x86_64):
      text       data        bss      total filename
       907        336         64       1307 system/serial.o
      3442       1242         54       4738 app/display.o

Co-authored-by: Sam Demeulemeester <38105886+x86fr@users.noreply.github.com>
This commit is contained in:
01e3 2022-06-19 07:40:30 -07:00 committed by GitHub
parent 680e6ad79b
commit 1c88824a7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 96 additions and 75 deletions

View File

@ -80,6 +80,11 @@ void display_init(void)
clear_screen(); clear_screen();
/* The commented horizontal lines provide visual cue for where and how
* they will appear on the screen. They are drawn down below using
* Extended ASCII characters.
*/
set_foreground_colour(BLACK); set_foreground_colour(BLACK);
set_background_colour(WHITE); set_background_colour(WHITE);
clear_screen_region(0, 0, 0, 27); clear_screen_region(0, 0, 0, 27);
@ -88,34 +93,30 @@ void display_init(void)
printc(0, 14, '+'); printc(0, 14, '+');
set_foreground_colour(WHITE); set_foreground_colour(WHITE);
set_background_colour(BLUE); set_background_colour(BLUE);
prints(0,28, "| "); prints(1, 0, "CLK/Temp: N/A | Pass %");
prints(1, 0, "CLK/Temp: N/A | Pass % "); prints(2, 0, "L1 Cache: N/A | Test %");
prints(2, 0, "L1 Cache: N/A | Test % "); prints(3, 0, "L2 Cache: N/A | Test #");
prints(3, 0, "L2 Cache: N/A | Test # "); prints(4, 0, "L3 Cache: N/A | Testing:");
prints(4, 0, "L3 Cache: N/A | Testing: "); prints(5, 0, "Memory : N/A | Pattern:");
prints(5, 0, "Memory : N/A | Pattern: "); // prints(6, 0, "--------------------------------------------------------------------------------");
prints(6, 0, "--------------------------------------------------------------------------------"); prints(7, 0, "CPU: SMP: N/A | Time: Status: Init.");
prints(7, 0, "CPU: SMP: N/A | Time: Status: Init. "); prints(8, 0, "Using: | Pass: Errors:");
prints(8, 0, "Using: | Pass: Errors: "); // prints(9, 0, "--------------------------------------------------------------------------------");
prints(9, 0, "--------------------------------------------------------------------------------");
// Redraw lines using box drawing characters. for (int i = 0;i < 80; i++) {
// Disable if TTY is enabled to avoid VT100 char replacements print_char(6, i, 0xc4);
if (!enable_tty) { print_char(9, i, 0xc4);
for (int i = 0;i < 80; i++) {
print_char(6, i, 0xc4);
print_char(9, i, 0xc4);
}
for (int i = 0; i < 6; i++) {
print_char(i, 28, 0xb3);
}
for (int i = 7; i < 10; i++) {
print_char(i, 42, 0xb3);
}
print_char(6, 28, 0xc1);
print_char(6, 42, 0xc2);
print_char(9, 42, 0xc1);
} }
for (int i = 0; i < 6; i++) {
print_char(i, 28, 0xb3);
}
for (int i = 7; i < 10; i++) {
print_char(i, 42, 0xb3);
}
print_char(6, 28, 0xc1);
print_char(6, 42, 0xc2);
print_char(9, 42, 0xc1);
set_foreground_colour(BLUE); set_foreground_colour(BLUE);
set_background_colour(WHITE); set_background_colour(WHITE);

View File

@ -67,33 +67,24 @@ void serial_echo_print(const char *p)
if (!port->enable) { if (!port->enable) {
return; return;
} }
/* Now, do each character */ /* Now, do each character */
while (*p) { while (*p) {
serial_wait_for_xmit(port);
/* Send the character out. */ /* Send the character out. */
serial_write_reg(port, UART_TX, *p); serial_wait_for_xmit(port);
if (*p==10) { serial_write_reg(port, UART_TX, *p++);
serial_wait_for_xmit(port);
serial_write_reg(port, UART_TX, 13);
}
p++;
} }
} }
void tty_print(int y, int x, const char *p) void tty_goto(int y, int x)
{ {
static char sx[3], sy[3]; static char s[3];
itoa(++x,sx);
itoa(++y,sy);
serial_echo_print("\x1b["); serial_echo_print("\x1b[");
serial_echo_print(sy); serial_echo_print(itoa(y + 1, s));
serial_echo_print(";"); serial_echo_print(";");
serial_echo_print(sx); serial_echo_print(itoa(x + 1, s));
serial_echo_print("H"); serial_echo_print("H");
serial_echo_print(p);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -135,8 +126,8 @@ void tty_init(void)
serial_write_reg(&console_serial, UART_LCR, lcr); /* Done with divisor */ serial_write_reg(&console_serial, UART_LCR, lcr); /* Done with divisor */
/* Prior to disabling interrupts, read the LSR and RBR registers */ /* Prior to disabling interrupts, read the LSR and RBR registers */
uart_status = serial_read_reg(&console_serial, UART_LSR); /* COM? LSR */ uart_status = serial_read_reg(&console_serial, UART_LSR); /* COM? LSR */
uart_status = serial_read_reg(&console_serial, UART_RX); /* COM? RBR */ uart_status = serial_read_reg(&console_serial, UART_RX); /* COM? RBR */
serial_write_reg(&console_serial, UART_IER, 0x00); /* Disable all interrupts */ serial_write_reg(&console_serial, UART_IER, 0x00); /* Disable all interrupts */
tty_clear_screen(); tty_clear_screen();
@ -146,7 +137,9 @@ void tty_init(void)
void tty_send_region(int start_row, int start_col, int end_row, int end_col) void tty_send_region(int start_row, int start_col, int end_row, int end_col)
{ {
char p[SCREEN_WIDTH+1]; char p[SCREEN_WIDTH+1];
int col_len = end_col - start_col; uint8_t ch;
int pos = 0;
int cur_inverse = -1, inverse = false;
if (start_col > (SCREEN_WIDTH - 1) || end_col > (SCREEN_WIDTH - 1)) { if (start_col > (SCREEN_WIDTH - 1) || end_col > (SCREEN_WIDTH - 1)) {
return; return;
@ -158,42 +151,69 @@ void tty_send_region(int start_row, int start_col, int end_row, int end_col)
for (int row = start_row; row <= end_row; row++) { for (int row = start_row; row <= end_row; row++) {
// Last line is inverted (Black on white) /* Move the cursor to the new position. If the starting col is not 0 or
if (row == SCREEN_HEIGHT-1) { * this is the first row we have to use absolute positioning, otherwise
tty_inverse(); * CR + LF can take us to col=0, row++ */
if (start_col || row == start_row) {
tty_goto(row, start_col);
} else {
serial_echo_print("\r\n");
} }
// Copy Shadow buffer to TTY buffer // Copy Shadow buffer to TTY buffer
pos = 0;
for (int col = start_col; col <= end_col; col++) { for (int col = start_col; col <= end_col; col++) {
p[col] = shadow_buffer[row][col].value & 0x7F;
inverse = ((shadow_buffer[row][col].attr & 0x70) >> 4 != BLUE);
if (cur_inverse != inverse) {
if (pos) {
p[pos] = '\0';
serial_echo_print(p);
pos = 0;
}
if (inverse) {
tty_inverse();
} else {
tty_normal();
}
cur_inverse = inverse;
}
/* Make sure only VT100 characters are sent. */
ch = shadow_buffer[row][col].ch;
switch (ch) {
case 32 ... 127:
break;
case 0xB3:
ch = '|';
break;
case 0xC1:
case 0xC2:
case 0xC4:
ch = '-';
break;
case 0xF8:
ch = '*';
break;
default:
ch = '?';
}
p[pos++] = ch;
} }
// Add string terminator if (pos) {
p[end_col+1] = '\0'; p[pos] = '\0';
serial_echo_print(p);
// For first line, title on top-left must be inverted
// Do the switch, send to TTY then continue to next line.
if (row == 0 && start_col == 0 && col_len > 28) {
tty_inverse();
p[28] = '\0';
tty_print(row,0,p);
tty_normal();
p[28] = '|';
tty_print(row, 28, p + 28);
continue;
}
// Replace degree symbol with '*' for tty to avoid a C437/VT100 translation table.
if (row == 1 && (shadow_buffer[1][25].value & 0xFF) == 0xF8) {
p[25] = 0x2A;
}
// Send row to TTY
tty_print(row, start_col, p + start_col);
// Revert to normal if last line.
if (row == SCREEN_HEIGHT-1) {
tty_normal();
} }
} }
} }