diff --git a/ports/atmel-samd/boards/openbook_m4/mpconfigboard.mk b/ports/atmel-samd/boards/openbook_m4/mpconfigboard.mk index a786b5ebc654a..a0f5ada80be5a 100644 --- a/ports/atmel-samd/boards/openbook_m4/mpconfigboard.mk +++ b/ports/atmel-samd/boards/openbook_m4/mpconfigboard.mk @@ -14,3 +14,4 @@ CIRCUITPY_KEYPAD = 1 CIRCUITPY_SYNTHIO = 0 CIRCUITPY_JPEGIO = 0 CIRCUITPY_FLOPPYIO = 0 +CIRCUITPY_TERMINALIO_VT100 = 0 diff --git a/ports/atmel-samd/boards/uartlogger2/mpconfigboard.mk b/ports/atmel-samd/boards/uartlogger2/mpconfigboard.mk index 4b23566f71fd0..c3626ab98f3bb 100644 --- a/ports/atmel-samd/boards/uartlogger2/mpconfigboard.mk +++ b/ports/atmel-samd/boards/uartlogger2/mpconfigboard.mk @@ -12,3 +12,4 @@ LONGINT_IMPL = MPZ CIRCUITPY_SPITARGET = 0 CIRCUITPY_SYNTHIO = 0 CIRCUITPY_JPEGIO = 0 +CIRCUITPY_TERMINALIO_VT100 = 0 diff --git a/shared-bindings/terminalio/Terminal.c b/shared-bindings/terminalio/Terminal.c index 5d79c88c60839..570449ad424a4 100644 --- a/shared-bindings/terminalio/Terminal.c +++ b/shared-bindings/terminalio/Terminal.c @@ -39,6 +39,8 @@ //| * ``ESC [ H`` - Move the cursor to 0,0. //| * ``ESC M`` - Move the cursor up one line, scrolling if necessary. //| * ``ESC D`` - Move the cursor down one line, scrolling if necessary. +//| * ``ESC [ r`` - Disable scrolling range (set to fullscreen). +//| * ``ESC [ nnnn ; mmmm r`` - Set scrolling range between rows nnnn and mmmm. //| * ``ESC [ ## m`` - Set the terminal display attributes. //| * ``ESC [ ## ; ## m`` - Set the terminal display attributes. //| * ``ESC [ ## ; ## ; ## m`` - Set the terminal display attributes. diff --git a/shared-module/terminalio/Terminal.c b/shared-module/terminalio/Terminal.c index d2cedf0661874..2828d0d3800c5 100644 --- a/shared-module/terminalio/Terminal.c +++ b/shared-module/terminalio/Terminal.c @@ -33,6 +33,8 @@ void common_hal_terminalio_terminal_construct(terminalio_terminal_obj_t *self, self->status_x = 0; self->status_y = 0; self->first_row = 0; + self->vt_scroll_top = 0; + self->vt_scroll_end = self->scroll_area->height_in_tiles - 1; common_hal_displayio_tilegrid_set_all_tiles(self->scroll_area, 0); if (self->status_bar) { common_hal_displayio_tilegrid_set_all_tiles(self->status_bar, 0); @@ -42,6 +44,8 @@ void common_hal_terminalio_terminal_construct(terminalio_terminal_obj_t *self, } size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, const byte *data, size_t len, int *errcode) { + #define SCRNMOD(x) (((x) + (self->scroll_area->top_left_y)) % (self->scroll_area->height_in_tiles)) + // Make sure the terminal is initialized before we do anything with it. if (self->scroll_area == NULL) { return len; @@ -114,7 +118,7 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con } } else if (c == 0x1b) { // Handle commands of the form [ESC]. where . is not yet known. - uint8_t vt_args[3] = {0, -1, -1}; + int16_t vt_args[3] = {0, 0, 0}; uint8_t j = 1; #if CIRCUITPY_TERMINALIO_VT100 uint8_t n_args = 1; @@ -158,8 +162,8 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con #endif } else { if (c == 'K') { - uint8_t clr_start = self->cursor_x; - uint8_t clr_end = self->scroll_area->width_in_tiles; + int16_t clr_start = self->cursor_x; + int16_t clr_end = self->scroll_area->width_in_tiles; #if CIRCUITPY_TERMINALIO_VT100 if (vt_args[0] == 1) { clr_start = 0; @@ -188,9 +192,6 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con if (vt_args[0] > 0) { vt_args[0]--; } - if (vt_args[1] == -1) { - vt_args[1] = 0; - } if (vt_args[1] > 0) { vt_args[1]--; } @@ -200,7 +201,7 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con if (vt_args[1] >= self->scroll_area->width_in_tiles) { vt_args[1] = self->scroll_area->width_in_tiles - 1; } - vt_args[0] = (vt_args[0] + self->scroll_area->top_left_y) % self->scroll_area->height_in_tiles; + vt_args[0] = SCRNMOD(vt_args[0]); self->cursor_x = vt_args[1]; self->cursor_y = vt_args[0]; start_y = self->cursor_y; @@ -215,43 +216,58 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con common_hal_displayio_palette_set_color(terminal_palette, 1, 0xffffff); } } + } else if (c == 'r') { + if (vt_args[0] < vt_args[1] && vt_args[0] >= 1 && vt_args[1] <= self->scroll_area->height_in_tiles) { + self->vt_scroll_top = vt_args[0] - 1; + self->vt_scroll_end = vt_args[1] - 1; + } else { + self->vt_scroll_top = 0; + self->vt_scroll_end = self->scroll_area->height_in_tiles - 1; + } + self->cursor_x = 0; + self->cursor_y = self->scroll_area->top_left_y % self->scroll_area->height_in_tiles; + start_y = self->cursor_y; #endif } i += j + 1; } #if CIRCUITPY_TERMINALIO_VT100 } else if (i[0] == 'M') { - if (self->cursor_y != self->scroll_area->top_left_y) { + if (self->cursor_y != SCRNMOD(self->vt_scroll_top)) { if (self->cursor_y > 0) { self->cursor_y = self->cursor_y - 1; } else { self->cursor_y = self->scroll_area->height_in_tiles - 1; } } else { - if (self->cursor_y > 0) { - common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, self->cursor_y - 1); + if (self->vt_scroll_top != 0 || self->vt_scroll_end != self->scroll_area->height_in_tiles) { + // Scroll range defined, manually move tiles to perform scroll + for (int16_t irow = self->vt_scroll_end - 1; irow >= self->vt_scroll_top; irow--) { + for (int16_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) { + common_hal_displayio_tilegrid_set_tile(self->scroll_area, icol, SCRNMOD(irow + 1), common_hal_displayio_tilegrid_get_tile(self->scroll_area, icol, SCRNMOD(irow))); + } + } + for (int16_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) { + common_hal_displayio_tilegrid_set_tile(self->scroll_area, icol, self->cursor_y, 0); + } } else { - common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, self->scroll_area->height_in_tiles - 1); - } - for (uint8_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) { - common_hal_displayio_tilegrid_set_tile(self->scroll_area, icol, self->scroll_area->top_left_y, 0); + // Full screen scroll, just set new top_y pointer and clear row + if (self->cursor_y > 0) { + common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, self->cursor_y - 1); + } else { + common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, self->scroll_area->height_in_tiles - 1); + } + for (uint16_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) { + common_hal_displayio_tilegrid_set_tile(self->scroll_area, icol, self->scroll_area->top_left_y, 0); + } + self->cursor_y = self->scroll_area->top_left_y; } - self->cursor_x = 0; - self->cursor_y = self->scroll_area->top_left_y; } start_y = self->cursor_y; i++; } else if (i[0] == 'D') { - self->cursor_y = (self->cursor_y + 1) % self->scroll_area->height_in_tiles; - if (self->cursor_y == self->scroll_area->top_left_y) { - common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, (self->cursor_y + 1) % self->scroll_area->height_in_tiles); - for (uint8_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) { - common_hal_displayio_tilegrid_set_tile(self->scroll_area, icol, self->cursor_y, 0); - } - self->cursor_x = 0; - } - start_y = self->cursor_y; + self->cursor_y++; i++; #endif } else if (i[0] == ']' && c == ';') { @@ -276,12 +292,28 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con self->cursor_y %= self->scroll_area->height_in_tiles; } if (self->cursor_y != start_y) { - // clear the new row in case of scroll up - if (self->cursor_y == self->scroll_area->top_left_y) { - for (uint16_t j = 0; j < self->scroll_area->width_in_tiles; j++) { - common_hal_displayio_tilegrid_set_tile(self->scroll_area, j, self->cursor_y, 0); + if (((self->cursor_y + self->scroll_area->height_in_tiles) - 1) % self->scroll_area->height_in_tiles == SCRNMOD(self->vt_scroll_end)) { + #if CIRCUITPY_TERMINALIO_VT100 + if (self->vt_scroll_top != 0 || self->vt_scroll_end != self->scroll_area->height_in_tiles) { + // Scroll range defined, manually move tiles to perform scroll + self->cursor_y = SCRNMOD(self->vt_scroll_end); + + for (int16_t irow = self->vt_scroll_top; irow < self->vt_scroll_end; irow++) { + for (int16_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) { + common_hal_displayio_tilegrid_set_tile(self->scroll_area, icol, SCRNMOD(irow), common_hal_displayio_tilegrid_get_tile(self->scroll_area, icol, SCRNMOD(irow + 1))); + } + } + } + #endif + if (self->vt_scroll_top == 0 && self->vt_scroll_end == self->scroll_area->height_in_tiles) { + // Full screen scroll, just set new top_y pointer + common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, (self->cursor_y + self->scroll_area->height_in_tiles + 1) % self->scroll_area->height_in_tiles); + } + // clear the new row in case of scroll up + for (int16_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) { + common_hal_displayio_tilegrid_set_tile(self->scroll_area, icol, self->cursor_y, 0); } - common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, (self->cursor_y + self->scroll_area->height_in_tiles + 1) % self->scroll_area->height_in_tiles); + self->cursor_x = 0; } start_y = self->cursor_y; } diff --git a/shared-module/terminalio/Terminal.h b/shared-module/terminalio/Terminal.h index 17230a74066c1..d617f571aed7d 100644 --- a/shared-module/terminalio/Terminal.h +++ b/shared-module/terminalio/Terminal.h @@ -23,6 +23,8 @@ typedef struct { uint16_t status_x; uint16_t status_y; uint16_t first_row; + uint16_t vt_scroll_top; + uint16_t vt_scroll_end; uint16_t osc_command; bool in_osc_command; } terminalio_terminal_obj_t;