diff --git a/user/ansi_parser.c b/user/ansi_parser.c index 17bbe0c..22b8cb4 100644 --- a/user/ansi_parser.c +++ b/user/ansi_parser.c @@ -22,18 +22,18 @@ static const char _ansi_eof_actions[] = { 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 0, 0, - 0, 0, 0, 0, 0, 0, 0 + 13, 13, 13, 13, 0, 0, 0, 0, + 0, 0, 0, 0 }; static const int ansi_start = 1; -static const int ansi_first_final = 30; +static const int ansi_first_final = 28; static const int ansi_error = 0; static const int ansi_en_CSI_body = 5; static const int ansi_en_OSC_body = 7; -static const int ansi_en_TITLE_body = 27; -static const int ansi_en_charsetcmd_body = 29; +static const int ansi_en_TITLE_body = 25; +static const int ansi_en_charsetcmd_body = 27; static const int ansi_en_main = 1; @@ -55,7 +55,7 @@ ansi_parser_reset(void) { } } -#define HISTORY_LEN 16 +#define HISTORY_LEN 10 #if DEBUG_ANSI static char history[HISTORY_LEN + 1]; @@ -164,8 +164,12 @@ ansi_parser(char newchar) return; case BEL: - apars_handle_bel(); - return; + // bel is also used to terminate OSC + if (!inside_osc) { + apars_handle_bel(); + return; + } + break; case ENQ: // respond with space (like xterm) UART_WriteChar(UART0, SP, UART_TIMEOUT_US); @@ -198,7 +202,7 @@ ansi_parser(char newchar) // The parser -/* #line 202 "user/ansi_parser.c" */ +/* #line 206 "user/ansi_parser.c" */ { const char *_acts; unsigned int _nacts; @@ -242,7 +246,7 @@ case 3: if ( 70 <= (*p) && (*p) <= 71 ) goto tr10; goto tr2; -case 30: +case 28: if ( (*p) == 27 ) goto tr1; goto tr0; @@ -282,9 +286,9 @@ case 6: } else goto tr16; goto tr2; -case 31: +case 29: goto tr2; -case 32: +case 30: if ( (*p) == 59 ) goto tr14; if ( (*p) < 64 ) { @@ -308,123 +312,107 @@ case 8: if ( (*p) == 59 ) goto tr21; goto tr2; -case 9: - switch( (*p) ) { - case 7: goto tr23; - case 27: goto tr24; - } - goto tr22; -case 33: - switch( (*p) ) { - case 7: goto tr23; - case 27: goto tr24; - } - goto tr22; -case 10: - if ( (*p) == 92 ) - goto tr25; - goto tr2; -case 34: +case 31: goto tr2; -case 11: +case 9: if ( (*p) == 84 ) - goto tr26; + goto tr22; goto tr2; -case 12: +case 10: if ( (*p) == 78 ) - goto tr27; + goto tr23; goto tr2; -case 13: +case 11: if ( 48 <= (*p) && (*p) <= 57 ) - goto tr28; + goto tr24; goto tr2; -case 14: +case 12: if ( (*p) == 61 ) - goto tr29; + goto tr25; goto tr2; -case 15: +case 13: switch( (*p) ) { - case 7: goto tr31; - case 27: goto tr32; + case 7: goto tr27; + case 27: goto tr28; } - goto tr30; -case 35: + goto tr26; +case 32: switch( (*p) ) { - case 7: goto tr31; - case 27: goto tr32; + case 7: goto tr27; + case 27: goto tr28; } - goto tr30; -case 16: + goto tr26; +case 14: if ( (*p) == 92 ) - goto tr33; + goto tr29; goto tr2; -case 17: +case 15: if ( (*p) == 73 ) - goto tr34; + goto tr30; goto tr2; -case 18: +case 16: if ( (*p) == 84 ) - goto tr35; + goto tr31; goto tr2; -case 19: +case 17: if ( (*p) == 76 ) - goto tr36; + goto tr32; goto tr2; -case 20: +case 18: if ( (*p) == 69 ) - goto tr37; + goto tr33; goto tr2; -case 21: +case 19: if ( (*p) == 61 ) - goto tr38; + goto tr21; goto tr2; -case 22: +case 20: if ( 48 <= (*p) && (*p) <= 57 ) - goto tr39; + goto tr34; goto tr2; -case 23: +case 21: if ( (*p) == 59 ) - goto tr40; + goto tr35; if ( 48 <= (*p) && (*p) <= 57 ) - goto tr39; + goto tr34; goto tr2; -case 24: +case 22: if ( 48 <= (*p) && (*p) <= 57 ) - goto tr41; + goto tr36; goto tr2; -case 25: +case 23: switch( (*p) ) { - case 7: goto tr42; - case 27: goto tr43; + case 7: goto tr37; + case 27: goto tr38; } if ( 48 <= (*p) && (*p) <= 57 ) - goto tr41; + goto tr36; goto tr2; -case 26: +case 24: if ( (*p) == 92 ) - goto tr42; + goto tr37; goto tr2; -case 27: +case 25: switch( (*p) ) { - case 7: goto tr45; - case 27: goto tr46; + case 7: goto tr40; + case 27: goto tr41; } - goto tr44; -case 36: + goto tr39; +case 33: switch( (*p) ) { - case 7: goto tr45; - case 27: goto tr46; + case 7: goto tr40; + case 27: goto tr41; } - goto tr44; -case 28: + goto tr39; +case 26: if ( (*p) == 92 ) - goto tr47; + goto tr42; goto tr2; -case 37: +case 34: goto tr2; -case 29: - goto tr48; -case 38: +case 27: + goto tr43; +case 35: goto tr2; } @@ -437,46 +425,41 @@ case 38: tr13: cs = 6; goto f10; tr14: cs = 6; goto f11; tr17: cs = 8; goto _again; - tr21: cs = 9; goto _again; - tr22: cs = 9; goto f14; - tr24: cs = 10; goto _again; - tr18: cs = 11; goto _again; - tr26: cs = 12; goto _again; - tr27: cs = 13; goto _again; - tr28: cs = 14; goto f10; - tr29: cs = 15; goto _again; - tr30: cs = 15; goto f14; - tr32: cs = 16; goto _again; - tr19: cs = 17; goto _again; - tr34: cs = 18; goto _again; - tr35: cs = 19; goto _again; - tr36: cs = 20; goto _again; - tr37: cs = 21; goto _again; - tr20: cs = 22; goto _again; - tr39: cs = 23; goto f10; - tr40: cs = 24; goto f11; - tr41: cs = 25; goto f10; - tr43: cs = 26; goto _again; - tr44: cs = 27; goto f14; - tr46: cs = 28; goto _again; - tr5: cs = 30; goto f2; - tr6: cs = 30; goto f3; - tr7: cs = 30; goto f4; - tr8: cs = 30; goto f5; - tr9: cs = 30; goto f6; - tr10: cs = 30; goto f7; - tr11: cs = 30; goto f8; - tr16: cs = 31; goto f13; - tr15: cs = 32; goto f12; - tr23: cs = 33; goto f15; - tr38: cs = 34; goto f6; - tr25: cs = 34; goto f16; - tr33: cs = 34; goto f18; + tr18: cs = 9; goto _again; + tr22: cs = 10; goto _again; + tr23: cs = 11; goto _again; + tr24: cs = 12; goto f10; + tr25: cs = 13; goto _again; + tr26: cs = 13; goto f14; + tr28: cs = 14; goto _again; + tr19: cs = 15; goto _again; + tr30: cs = 16; goto _again; + tr31: cs = 17; goto _again; + tr32: cs = 18; goto _again; + tr33: cs = 19; goto _again; + tr20: cs = 20; goto _again; + tr34: cs = 21; goto f10; + tr35: cs = 22; goto f11; + tr36: cs = 23; goto f10; + tr38: cs = 24; goto _again; + tr39: cs = 25; goto f14; + tr41: cs = 26; goto _again; + tr5: cs = 28; goto f2; + tr6: cs = 28; goto f3; + tr7: cs = 28; goto f4; + tr8: cs = 28; goto f5; + tr9: cs = 28; goto f6; + tr10: cs = 28; goto f7; + tr11: cs = 28; goto f8; + tr16: cs = 29; goto f13; + tr15: cs = 30; goto f12; + tr21: cs = 31; goto f6; + tr29: cs = 31; goto f16; + tr37: cs = 31; goto f17; + tr27: cs = 32; goto f15; + tr40: cs = 33; goto f18; tr42: cs = 34; goto f19; - tr31: cs = 35; goto f17; - tr45: cs = 36; goto f15; - tr47: cs = 37; goto f16; - tr48: cs = 38; goto f20; + tr43: cs = 35; goto f20; f1: _acts = _ansi_actions + 1; goto execFuncs; f4: _acts = _ansi_actions + 3; goto execFuncs; @@ -487,25 +470,25 @@ case 38: f0: _acts = _ansi_actions + 13; goto execFuncs; f5: _acts = _ansi_actions + 15; goto execFuncs; f6: _acts = _ansi_actions + 17; goto execFuncs; - f19: _acts = _ansi_actions + 19; goto execFuncs; + f17: _acts = _ansi_actions + 19; goto execFuncs; f14: _acts = _ansi_actions + 21; goto execFuncs; - f16: _acts = _ansi_actions + 23; goto execFuncs; - f18: _acts = _ansi_actions + 25; goto execFuncs; + f19: _acts = _ansi_actions + 23; goto execFuncs; + f16: _acts = _ansi_actions + 25; goto execFuncs; f8: _acts = _ansi_actions + 27; goto execFuncs; f3: _acts = _ansi_actions + 29; goto execFuncs; f7: _acts = _ansi_actions + 31; goto execFuncs; f2: _acts = _ansi_actions + 33; goto execFuncs; f20: _acts = _ansi_actions + 35; goto execFuncs; f12: _acts = _ansi_actions + 37; goto execFuncs; - f15: _acts = _ansi_actions + 40; goto execFuncs; - f17: _acts = _ansi_actions + 43; goto execFuncs; + f18: _acts = _ansi_actions + 40; goto execFuncs; + f15: _acts = _ansi_actions + 43; goto execFuncs; execFuncs: _nacts = *_acts++; while ( _nacts-- > 0 ) { switch ( *_acts++ ) { case 0: -/* #line 173 "user/ansi_parser.rl" */ +/* #line 177 "user/ansi_parser.rl" */ { if ((*p) != 0) { apars_handle_plainchar((*p)); @@ -513,7 +496,7 @@ execFuncs: } break; case 1: -/* #line 182 "user/ansi_parser.rl" */ +/* #line 186 "user/ansi_parser.rl" */ { // Reset the CSI builder csi_leading = csi_char = 0; @@ -529,13 +512,13 @@ execFuncs: } break; case 2: -/* #line 196 "user/ansi_parser.rl" */ +/* #line 200 "user/ansi_parser.rl" */ { csi_leading = (*p); } break; case 3: -/* #line 200 "user/ansi_parser.rl" */ +/* #line 204 "user/ansi_parser.rl" */ { if (csi_cnt == 0) csi_cnt = 1; // x10 + digit @@ -545,7 +528,7 @@ execFuncs: } break; case 4: -/* #line 208 "user/ansi_parser.rl" */ +/* #line 212 "user/ansi_parser.rl" */ { if (csi_cnt == 0) csi_cnt = 1; // handle case when first arg is empty csi_cnt++; @@ -553,7 +536,7 @@ execFuncs: } break; case 5: -/* #line 214 "user/ansi_parser.rl" */ +/* #line 218 "user/ansi_parser.rl" */ { csi_char = (*p); apars_handle_CSI(csi_leading, csi_n, csi_cnt, csi_char); @@ -561,15 +544,15 @@ execFuncs: } break; case 6: -/* #line 220 "user/ansi_parser.rl" */ +/* #line 224 "user/ansi_parser.rl" */ { - ansi_warn("Invalid escape sequence discarded."); + ansi_warn("Parser error."); apars_handle_badseq(); {cs = 1;goto _again;} } break; case 7: -/* #line 238 "user/ansi_parser.rl" */ +/* #line 242 "user/ansi_parser.rl" */ { csi_ni = 0; @@ -587,16 +570,16 @@ execFuncs: } break; case 8: -/* #line 255 "user/ansi_parser.rl" */ +/* #line 259 "user/ansi_parser.rl" */ { osc_bi = 0; osc_buffer[0] = '\0'; inside_osc = true; - {cs = 27;goto _again;} + {cs = 25;goto _again;} } break; case 9: -/* #line 262 "user/ansi_parser.rl" */ +/* #line 266 "user/ansi_parser.rl" */ { apars_handle_OSC_SetScreenSize(csi_n[0], csi_n[1]); inside_osc = false; @@ -604,13 +587,13 @@ execFuncs: } break; case 10: -/* #line 268 "user/ansi_parser.rl" */ +/* #line 272 "user/ansi_parser.rl" */ { osc_buffer[osc_bi++] = (*p); } break; case 11: -/* #line 272 "user/ansi_parser.rl" */ +/* #line 276 "user/ansi_parser.rl" */ { osc_buffer[osc_bi++] = '\0'; apars_handle_OSC_SetTitle(osc_buffer); @@ -619,7 +602,7 @@ execFuncs: } break; case 12: -/* #line 279 "user/ansi_parser.rl" */ +/* #line 283 "user/ansi_parser.rl" */ { osc_buffer[osc_bi++] = '\0'; apars_handle_OSC_SetButton(csi_n[0], osc_buffer); @@ -628,42 +611,42 @@ execFuncs: } break; case 13: -/* #line 312 "user/ansi_parser.rl" */ +/* #line 316 "user/ansi_parser.rl" */ { apars_handle_hashCode((*p)); {cs = 1;goto _again;} } break; case 14: -/* #line 317 "user/ansi_parser.rl" */ +/* #line 321 "user/ansi_parser.rl" */ { apars_handle_shortCode((*p)); {cs = 1;goto _again;} } break; case 15: -/* #line 322 "user/ansi_parser.rl" */ +/* #line 326 "user/ansi_parser.rl" */ { apars_handle_setXCtrls((*p)); // weird control settings like 7 bit / 8 bit mode {cs = 1;goto _again;} } break; case 16: -/* #line 327 "user/ansi_parser.rl" */ +/* #line 331 "user/ansi_parser.rl" */ { // abuse the buffer for storing the leading char osc_buffer[0] = (*p); - {cs = 29;goto _again;} + {cs = 27;goto _again;} } break; case 17: -/* #line 333 "user/ansi_parser.rl" */ +/* #line 337 "user/ansi_parser.rl" */ { apars_handle_characterSet(osc_buffer[0], (*p)); {cs = 1;goto _again;} } break; -/* #line 667 "user/ansi_parser.c" */ +/* #line 650 "user/ansi_parser.c" */ } } goto _again; @@ -681,16 +664,16 @@ _again: while ( __nacts-- > 0 ) { switch ( *__acts++ ) { case 6: -/* #line 220 "user/ansi_parser.rl" */ +/* #line 224 "user/ansi_parser.rl" */ { - ansi_warn("Invalid escape sequence discarded."); + ansi_warn("Parser error."); apars_handle_badseq(); {cs = 1; if ( p == pe ) goto _test_eof; goto _again;} } break; -/* #line 694 "user/ansi_parser.c" */ +/* #line 677 "user/ansi_parser.c" */ } } } @@ -698,7 +681,7 @@ goto _again;} _out: {} } -/* #line 357 "user/ansi_parser.rl" */ +/* #line 361 "user/ansi_parser.rl" */ } diff --git a/user/ansi_parser.rl b/user/ansi_parser.rl index 45b481c..0840d5a 100644 --- a/user/ansi_parser.rl +++ b/user/ansi_parser.rl @@ -25,7 +25,7 @@ ansi_parser_reset(void) { } } -#define HISTORY_LEN 16 +#define HISTORY_LEN 10 #if DEBUG_ANSI static char history[HISTORY_LEN + 1]; @@ -128,8 +128,12 @@ ansi_parser(char newchar) return; case BEL: - apars_handle_bel(); - return; + // bel is also used to terminate OSC + if (!inside_osc) { + apars_handle_bel(); + return; + } + break; case ENQ: // respond with space (like xterm) UART_WriteChar(UART0, SP, UART_TIMEOUT_US); @@ -166,7 +170,7 @@ ansi_parser(char newchar) ESC = 27; NOESC = (any - ESC); TOK_ST = ESC '\\'; # String terminator - used for OSC commands - OSC_END = ('\a' | ESC '\\'); + OSC_END = ('\a' | TOK_ST); # --- Regular characters to be printed --- @@ -218,7 +222,7 @@ ansi_parser(char newchar) } action errBadSeq { - ansi_warn("Invalid escape sequence discarded."); + ansi_warn("Parser error."); apars_handle_badseq(); fgoto main; } @@ -287,7 +291,7 @@ ansi_parser(char newchar) OSC_body := ( ("BTN" digit @CSI_digit '=' (NOESC @OSC_text_char)* OSC_END @OSC_button) | ("TITLE=" @SetTitle_start) | - ("0;" (NOESC @OSC_text_char)* OSC_END @OSC_title) | + ("0;" @SetTitle_start) | ('W' (digit @CSI_digit)+ ';' @CSI_semi (digit @CSI_digit)+ OSC_END @OSC_resize) ) $!errBadSeq; diff --git a/user/ansi_parser_callbacks.c b/user/ansi_parser_callbacks.c index 4801b0f..ec74486 100644 --- a/user/ansi_parser_callbacks.c +++ b/user/ansi_parser_callbacks.c @@ -69,7 +69,7 @@ apars_handle_plainchar(char c) return; fail: - ansi_warn("Bad UTF-8"); + ansi_warn("Bad UTF-8: %0Xh", c); apars_reset_utf8buffer(); } @@ -254,7 +254,7 @@ apars_handle_CSI(char leadchar, int *params, int count, char keychar) screen_set_cursors_alt_mode(yn); } else { - ansi_warn("NOIMPL DEC opt %d", n); +// ansi_warn("NOIMPL DEC opt %d", n); } } else { @@ -262,7 +262,7 @@ apars_handle_CSI(char leadchar, int *params, int count, char keychar) screen_set_insert_mode(yn); } else { - ansi_warn("NOIMPL flag %d", n); +// ansi_warn("NOIMPL flag %d", n); } } } @@ -356,12 +356,12 @@ apars_handle_CSI(char leadchar, int *params, int count, char keychar) case 'g': // TODO clear tab - ansi_warn("NOIMPL clear tab"); +// ansi_warn("NOIMPL clear tab"); break; case 'Z': // TODO back tab - ansi_warn("NOIMPL cursor back tab"); +// ansi_warn("NOIMPL cursor back tab"); break; case 'c': // CSI-c @@ -384,7 +384,7 @@ void ICACHE_FLASH_ATTR apars_handle_hashCode(char c) break; default: - ansi_warn("Unknown # sequence: %c", c); + ansi_warn("Bad seq: ESC # %c", c); } } @@ -435,7 +435,7 @@ void ICACHE_FLASH_ATTR apars_handle_shortCode(char c) break; default: - ansi_warn("Unknown 1-char seq %c", c); + ansi_warn("Bad seq: ESC %c", c); } } @@ -445,7 +445,7 @@ void ICACHE_FLASH_ATTR apars_handle_shortCode(char c) void ICACHE_FLASH_ATTR apars_handle_OSC_SetScreenSize(int rows, int cols) { - info("OSC: Set screen size to %d x %d", rows, cols); +// info("OSC: Set screen size to %d x %d", rows, cols); screen_resize(rows, cols); } @@ -455,7 +455,7 @@ void ICACHE_FLASH_ATTR apars_handle_OSC_SetButton(int num, const char *buffer) { strncpy(termconf_scratch.btn[num-1], buffer, TERM_BTN_LEN); - info("OSC: Set BTN%d = %s", num, buffer); +// info("OSC: Set BTN%d = %s", num, buffer); screen_notifyChange(CHANGE_LABELS); } @@ -463,6 +463,6 @@ void ICACHE_FLASH_ATTR apars_handle_OSC_SetTitle(const char *buffer) { strncpy(termconf_scratch.title, buffer, TERM_TITLE_LEN); - info("OSC: Set TITLE = %s", buffer); +// info("OSC: Set TITLE = %s", buffer); screen_notifyChange(CHANGE_LABELS); } diff --git a/user/screen.c b/user/screen.c index fd849d1..29a101b 100644 --- a/user/screen.c +++ b/user/screen.c @@ -128,7 +128,7 @@ void terminal_apply_settings_noclear(void) if (termconf->display_tout_ms == 0) termconf->display_tout_ms = SCR_DEF_DISPLAY_TOUT_MS; memcpy(&termconf_scratch, termconf, sizeof(TerminalConfigBundle)); - if (W*H >= MAX_SCREEN_SIZE) { + if (W*H > MAX_SCREEN_SIZE) { error("BAD SCREEN SIZE: %d rows x %d cols", H, W); error("reverting terminal settings to default"); terminal_restore_defaults(); diff --git a/user/screen.h b/user/screen.h index 6ca731e..b174af2 100644 --- a/user/screen.h +++ b/user/screen.h @@ -62,8 +62,7 @@ typedef enum { #define SCR_DEF_TITLE "ESPTerm" /** Maximum screen size (determines size of the static data array) */ -#define MAX_SCREEN_SIZE (80*30) - +#define MAX_SCREEN_SIZE (80*25) typedef struct { u32 width; diff --git a/user/serial.c b/user/serial.c index 8349788..056a86c 100644 --- a/user/serial.c +++ b/user/serial.c @@ -4,6 +4,42 @@ #include "ansi_parser.h" #include "syscfg.h" +#define LOGBUF_SIZE 1500 +static char logbuf[LOGBUF_SIZE]; +static u32 lb_nw = 1; +static u32 lb_ls = 0; +static ETSTimer flushLogTimer; + +static void buf_putc(char c) +{ + if (lb_ls != lb_nw) { + logbuf[lb_nw++] = c; + if (lb_nw >= LOGBUF_SIZE) lb_nw = 0; + } +} + +static void buf_pop(void *unused) +{ + u32 quantity = 32; + u32 old_ls; + while (quantity > 0) { + // stop when done + if ((lb_ls == lb_nw-1) || (lb_ls == LOGBUF_SIZE-1 && lb_nw == 0)) break; + + old_ls = lb_ls; + lb_ls++; + if (lb_ls >= LOGBUF_SIZE) lb_ls = 0; + + if (OK == UART_WriteCharCRLF(UART1, logbuf[lb_ls], 2000)) { + quantity--; + } else { + // try another time + lb_ls = old_ls; + break; + } + } +} + /** * Init the serial ports */ @@ -14,8 +50,15 @@ void ICACHE_FLASH_ATTR serialInitBase(void) UART_SetParity(UART1, PARITY_NONE); UART_SetStopBits(UART1, ONE_STOP_BIT); UART_SetBaudrate(UART1, BIT_RATE_115200); - UART_SetPrintPort(UART1); + //UART_SetPrintPort(UART1); + os_install_putc1(buf_putc); UART_SetupAsyncReceiver(); + + // 1 ms timer + os_timer_disarm(&flushLogTimer); + os_timer_setfn(&flushLogTimer, buf_pop, NULL); + //os_timer_arm(&flushLogTimer, 1, 1); + ets_timer_arm_new(&flushLogTimer, 1, 500, 0); // us timer } /**