Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ports/atmel-samd/mpconfigport.mk
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ CIRCUITPY_ZLIB = 0

# Turn off a few more things that don't fit in 192kB

CIRCUITPY_TERMINALIO_VT100 = 1

ifeq ($(INTERNAL_FLASH_FILESYSTEM),1)
CIRCUITPY_ONEWIREIO ?= 0
CIRCUITPY_SAFEMODE_PY ?= 0
Expand Down
3 changes: 3 additions & 0 deletions py/circuitpy_mpconfig.mk
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,9 @@ CFLAGS += -DCIRCUITPY_SYS=$(CIRCUITPY_SYS)
CIRCUITPY_TERMINALIO ?= $(CIRCUITPY_DISPLAYIO)
CFLAGS += -DCIRCUITPY_TERMINALIO=$(CIRCUITPY_TERMINALIO)

CIRCUITPY_TERMINALIO_VT100 ?= $(CIRCUITPY_TERMINALIO)
CFLAGS += -DCIRCUITPY_TERMINALIO_VT100=$(CIRCUITPY_TERMINALIO_VT100)

CIRCUITPY_FONTIO ?= $(call enable-if-all,$(CIRCUITPY_DISPLAYIO) $(CIRCUITPY_TERMINALIO))
CFLAGS += -DCIRCUITPY_FONTIO=$(CIRCUITPY_FONTIO)

Expand Down
11 changes: 9 additions & 2 deletions shared-bindings/terminalio/Terminal.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,18 @@
//|
//| VT100 control sequences:
//| * ``ESC [ K`` - Clear the remainder of the line
//| * ``ESC [ 0 K`` - Clear the remainder of the line
//| * ``ESC [ 1 K`` - Clear start of the line to cursor
//| * ``ESC [ 2 K`` - Clear the entire line
//| * ``ESC [ #### D`` - Move the cursor to the left by ####
//| * ``ESC [ 2 J`` - Erase the entire display
//| * ``ESC [ nnnn ; mmmm H`` - Move the cursor to mmmm, nnnn.
//| * ``ESC [ nn m`` - Set the terminal display attributes.
//| * ``ESC [ nn ; nn m`` - Set the terminal display attributes.
//| * ``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 [ ## m`` - Set the terminal display attributes.
//| * ``ESC [ ## ; ## m`` - Set the terminal display attributes.
//| * ``ESC [ ## ; ## ; ## m`` - Set the terminal display attributes.
//|
//| Supported Display attributes:
//| 0 - Reset all attributes
Expand Down
171 changes: 110 additions & 61 deletions shared-module/terminalio/Terminal.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
return len;
}

#if CIRCUITPY_TERMINALIO_VT100
uint32_t _select_color(uint16_t ascii_color) {
uint32_t color_value = 0;
if ((ascii_color & 1) > 0) {
Expand All @@ -63,6 +64,8 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
}

displayio_palette_t *terminal_palette = self->scroll_area->pixel_shader;
#endif

const byte *i = data;
uint16_t start_y = self->cursor_y;
while (i < data + len) {
Expand Down Expand Up @@ -111,99 +114,145 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con
}
} else if (c == 0x1b) {
// Handle commands of the form [ESC].<digits><command-char> where . is not yet known.
uint16_t n = 0;
uint8_t vt_args[3] = {0, -1, -1};
uint8_t n_args = 1;
uint8_t j = 1;
for (; j < 6; j++) {
if ('0' <= i[j] && i[j] <= '9') {
n = n * 10 + (i[j] - '0');
vt_args[0] = vt_args[0] * 10 + (i[j] - '0');
} else {
c = i[j];
break;
}
}
if (i[0] == '[') {
if (i[1] == 'K') {
// Clear the rest of the line.
for (uint16_t k = self->cursor_x; k < self->scroll_area->width_in_tiles; k++) {
common_hal_displayio_tilegrid_set_tile(self->scroll_area, k, self->cursor_y, 0);
for (uint8_t i_args = 1; i_args < 3 && c == ';'; i_args++) {
vt_args[i_args] = 0;
for (++j; j < 9; j++) {
if ('0' <= i[j] && i[j] <= '9') {
vt_args[i_args] = vt_args[i_args] * 10 + (i[j] - '0');
n_args = i_args + 1;
} else {
c = i[j];
break;
}
}
}
if (c == '?') {
#if CIRCUITPY_TERMINALIO_VT100
if (i[2] == '2' && i[3] == '5') {
// cursor visibility commands
if (i[4] == 'h') {
// make cursor visible
// not implemented yet
} else if (i[4] == 'l') {
// make cursor invisible
// not implemented yet
}
}
i += 2;
i += 5;
#endif
} else {
if (c == 'D') {
if (n > self->cursor_x) {
if (c == 'K') {
uint8_t clr_start = self->cursor_x;
uint8_t clr_end = self->scroll_area->width_in_tiles;
#if CIRCUITPY_TERMINALIO_VT100
if (vt_args[0] == 1) {
clr_start = 0;
clr_end = self->cursor_x;
} else if (vt_args[0] == 2) {
clr_start = 0;
}
#endif
// Clear the (start/rest/all) of the line.
for (uint16_t k = clr_start; k < clr_end; k++) {
common_hal_displayio_tilegrid_set_tile(self->scroll_area, k, self->cursor_y, 0);
}
} else if (c == 'D') {
if (vt_args[0] > self->cursor_x) {
self->cursor_x = 0;
} else {
self->cursor_x -= n;
self->cursor_x -= vt_args[0];
}
}
if (c == 'J') {
if (n == 2) {
} else if (c == 'J') {
if (vt_args[0] == 2) {
common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, 0);
self->cursor_x = self->cursor_y = start_y = 0;
n = 0;
common_hal_displayio_tilegrid_set_all_tiles(self->scroll_area, 0);
}
}
if (c == 'm') {
if ((n >= 40 && n <= 47) || (n >= 30 && n <= 37)) {
common_hal_displayio_palette_set_color(terminal_palette, 1 - (n / 40), _select_color(n % 10));
} else if (c == 'H') {
if (vt_args[0] > 0) {
vt_args[0]--;
}
if (n == 0) {
common_hal_displayio_palette_set_color(terminal_palette, 0, 0x000000);
common_hal_displayio_palette_set_color(terminal_palette, 1, 0xffffff);
if (vt_args[1] == -1) {
vt_args[1] = 0;
}
}
if (c == ';') {
uint16_t m = 0;
for (++j; j < 9; j++) {
if ('0' <= i[j] && i[j] <= '9') {
m = m * 10 + (i[j] - '0');
} else {
c = i[j];
break;
}
if (vt_args[1] > 0) {
vt_args[1]--;
}
if (c == 'H') {
if (n > 0) {
n--;
}
if (m > 0) {
m--;
}
if (n >= self->scroll_area->height_in_tiles) {
n = self->scroll_area->height_in_tiles - 1;
}
if (m >= self->scroll_area->width_in_tiles) {
m = self->scroll_area->width_in_tiles - 1;
}
n = (n + self->scroll_area->top_left_y) % self->scroll_area->height_in_tiles;
self->cursor_x = m;
self->cursor_y = n;
start_y = self->cursor_y;
if (vt_args[0] >= self->scroll_area->height_in_tiles) {
vt_args[0] = self->scroll_area->height_in_tiles - 1;
}
if (c == 'm') {
if ((n >= 40 && n <= 47) || (n >= 30 && n <= 37)) {
common_hal_displayio_palette_set_color(terminal_palette, 1 - (n / 40), _select_color(n % 10));
}
if (n == 0) {
common_hal_displayio_palette_set_color(terminal_palette, 0, 0x000000);
common_hal_displayio_palette_set_color(terminal_palette, 1, 0xffffff);
}
if ((m >= 40 && m <= 47) || (m >= 30 && m <= 37)) {
common_hal_displayio_palette_set_color(terminal_palette, 1 - (m / 40), _select_color(m % 10));
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;
self->cursor_x = vt_args[1];
self->cursor_y = vt_args[0];
start_y = self->cursor_y;
#if CIRCUITPY_TERMINALIO_VT100
} else if (c == 'm') {
for (uint8_t i_args = 0; i_args < n_args; i_args++) {
if ((vt_args[i_args] >= 40 && vt_args[i_args] <= 47) || (vt_args[i_args] >= 30 && vt_args[i_args] <= 37)) {
common_hal_displayio_palette_set_color(terminal_palette, 1 - (vt_args[i_args] / 40), _select_color(vt_args[i_args] % 10));
}
if (m == 0) {
if (vt_args[i_args] == 0) {
common_hal_displayio_palette_set_color(terminal_palette, 0, 0x000000);
common_hal_displayio_palette_set_color(terminal_palette, 1, 0xffffff);
}
}
#endif
}
i += j + 1;
continue;
}
#if CIRCUITPY_TERMINALIO_VT100
} else if (i[0] == 'M') {
if (self->cursor_y != self->scroll_area->top_left_y) {
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);
} 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);
}

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;
i++;
#endif
} else if (i[0] == ']' && c == ';') {
self->in_osc_command = true;
self->osc_command = n;
self->osc_command = vt_args[0];
i += j + 1;
}
}
Expand Down
Loading