diff --git a/CMakeLists.txt b/CMakeLists.txt index edf13be..3c24afe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -124,7 +124,7 @@ set(SOURCE_FILES user/persist.h include/helpers.h user/syscfg.c - user/syscfg.h) + user/syscfg.h user/ascii.h) include_directories(include) include_directories(user) diff --git a/html_orig/js/app.js b/html_orig/js/app.js index baa1f33..892c35d 100644 --- a/html_orig/js/app.js +++ b/html_orig/js/app.js @@ -2077,7 +2077,6 @@ var Input = (function() { onTap: sendPosMsg, sendString: sendStrMsg, setAlts: function(cu, np, fn) { - console.log("Set alts ", cu, np, fn); if (opts.cu_alt != cu || opts.np_alt != np || opts.fn_alt != fn) { opts.cu_alt = cu; opts.np_alt = np; diff --git a/html_orig/jssrc/term.js b/html_orig/jssrc/term.js index 8a51b8f..5541ca3 100644 --- a/html_orig/jssrc/term.js +++ b/html_orig/jssrc/term.js @@ -520,7 +520,6 @@ var Input = (function() { onTap: sendPosMsg, sendString: sendStrMsg, setAlts: function(cu, np, fn) { - console.log("Set alts ", cu, np, fn); if (opts.cu_alt != cu || opts.np_alt != np || opts.fn_alt != fn) { opts.cu_alt = cu; opts.np_alt = np; diff --git a/user/ansi_parser.c b/user/ansi_parser.c index 3bea038..17bbe0c 100644 --- a/user/ansi_parser.c +++ b/user/ansi_parser.c @@ -3,10 +3,12 @@ #include #include "ansi_parser.h" #include "screen.h" +#include "ascii.h" +#include "uart_driver.h" /* Ragel constants block */ -/* #line 10 "user/ansi_parser.c" */ +/* #line 12 "user/ansi_parser.c" */ static const char _ansi_actions[] = { 0, 1, 0, 1, 1, 1, 2, 1, 3, 1, 4, 1, 5, 1, 6, 1, @@ -35,10 +37,11 @@ static const int ansi_en_charsetcmd_body = 29; static const int ansi_en_main = 1; -/* #line 9 "user/ansi_parser.rl" */ +/* #line 11 "user/ansi_parser.rl" */ static volatile int cs = -1; +static volatile bool inside_osc = false; volatile u32 ansi_parser_char_cnt = 0; @@ -46,6 +49,7 @@ void ICACHE_FLASH_ATTR ansi_parser_reset(void) { if (cs != ansi_start) { cs = ansi_start; + inside_osc = false; apars_reset_utf8buffer(); ansi_warn("Parser timeout, state reset"); } @@ -93,7 +97,7 @@ apars_handle_badseq(void) * \param len - length of the newdata buffer */ void ICACHE_FLASH_ATTR -ansi_parser(const char *newdata, size_t len) +ansi_parser(char newchar) { // The CSI code is built here static char csi_leading; //!< Leading char, 0 if none @@ -102,42 +106,99 @@ ansi_parser(const char *newdata, size_t len) static int csi_n[CSI_N_MAX]; //!< Param digits static char csi_char; //!< CSI action char (end) static char osc_buffer[OSC_CHAR_MAX]; - static int osc_bi; + static int osc_bi; // buffer char index + // This is used to detect timeout delay (time since last rx char) ansi_parser_char_cnt++; - if (len == 0) len = strlen(newdata); - - // Load new data to Ragel vars - const char *p = newdata; - const char *eof = NULL; - const char *pe = newdata + len; - // Init Ragel on the first run if (cs == -1) { -/* #line 120 "user/ansi_parser.c" */ +/* #line 118 "user/ansi_parser.c" */ { cs = ansi_start; } -/* #line 89 "user/ansi_parser.rl" */ +/* #line 87 "user/ansi_parser.rl" */ -#if DEBUG_ANSI - memset(history, 0, sizeof(history)); -#endif + #if DEBUG_ANSI + memset(history, 0, sizeof(history)); + #endif } -#if DEBUG_ANSI - for(int i=len; i= ' ' + + // bypass the parser for simple characters (speed-up) + if (cs == ansi_start) { + apars_handle_plainchar(newchar); + return; + } } - strcpy(&history[HISTORY_LEN-len], newdata); -#endif + + // Load new data to Ragel vars + const char *p = &newchar; + const char *eof = NULL; + const char *pe = &newchar + 1; // The parser -/* #line 141 "user/ansi_parser.c" */ +/* #line 202 "user/ansi_parser.c" */ { const char *_acts; unsigned int _nacts; @@ -444,7 +505,7 @@ execFuncs: while ( _nacts-- > 0 ) { switch ( *_acts++ ) { case 0: -/* #line 112 "user/ansi_parser.rl" */ +/* #line 173 "user/ansi_parser.rl" */ { if ((*p) != 0) { apars_handle_plainchar((*p)); @@ -452,7 +513,7 @@ execFuncs: } break; case 1: -/* #line 121 "user/ansi_parser.rl" */ +/* #line 182 "user/ansi_parser.rl" */ { // Reset the CSI builder csi_leading = csi_char = 0; @@ -468,13 +529,13 @@ execFuncs: } break; case 2: -/* #line 135 "user/ansi_parser.rl" */ +/* #line 196 "user/ansi_parser.rl" */ { csi_leading = (*p); } break; case 3: -/* #line 139 "user/ansi_parser.rl" */ +/* #line 200 "user/ansi_parser.rl" */ { if (csi_cnt == 0) csi_cnt = 1; // x10 + digit @@ -484,7 +545,7 @@ execFuncs: } break; case 4: -/* #line 147 "user/ansi_parser.rl" */ +/* #line 208 "user/ansi_parser.rl" */ { if (csi_cnt == 0) csi_cnt = 1; // handle case when first arg is empty csi_cnt++; @@ -492,7 +553,7 @@ execFuncs: } break; case 5: -/* #line 153 "user/ansi_parser.rl" */ +/* #line 214 "user/ansi_parser.rl" */ { csi_char = (*p); apars_handle_CSI(csi_leading, csi_n, csi_cnt, csi_char); @@ -500,7 +561,7 @@ execFuncs: } break; case 6: -/* #line 159 "user/ansi_parser.rl" */ +/* #line 220 "user/ansi_parser.rl" */ { ansi_warn("Invalid escape sequence discarded."); apars_handle_badseq(); @@ -508,7 +569,7 @@ execFuncs: } break; case 7: -/* #line 177 "user/ansi_parser.rl" */ +/* #line 238 "user/ansi_parser.rl" */ { csi_ni = 0; @@ -520,69 +581,75 @@ execFuncs: osc_bi = 0; osc_buffer[0] = '\0'; + inside_osc = true; + {cs = 7;goto _again;} } break; case 8: -/* #line 192 "user/ansi_parser.rl" */ +/* #line 255 "user/ansi_parser.rl" */ { osc_bi = 0; osc_buffer[0] = '\0'; + inside_osc = true; {cs = 27;goto _again;} } break; case 9: -/* #line 198 "user/ansi_parser.rl" */ +/* #line 262 "user/ansi_parser.rl" */ { apars_handle_OSC_SetScreenSize(csi_n[0], csi_n[1]); + inside_osc = false; {cs = 1;goto _again;} } break; case 10: -/* #line 203 "user/ansi_parser.rl" */ +/* #line 268 "user/ansi_parser.rl" */ { osc_buffer[osc_bi++] = (*p); } break; case 11: -/* #line 207 "user/ansi_parser.rl" */ +/* #line 272 "user/ansi_parser.rl" */ { osc_buffer[osc_bi++] = '\0'; apars_handle_OSC_SetTitle(osc_buffer); + inside_osc = false; {cs = 1;goto _again;} } break; case 12: -/* #line 213 "user/ansi_parser.rl" */ +/* #line 279 "user/ansi_parser.rl" */ { osc_buffer[osc_bi++] = '\0'; apars_handle_OSC_SetButton(csi_n[0], osc_buffer); + inside_osc = false; {cs = 1;goto _again;} } break; case 13: -/* #line 245 "user/ansi_parser.rl" */ +/* #line 312 "user/ansi_parser.rl" */ { apars_handle_hashCode((*p)); {cs = 1;goto _again;} } break; case 14: -/* #line 250 "user/ansi_parser.rl" */ +/* #line 317 "user/ansi_parser.rl" */ { apars_handle_shortCode((*p)); {cs = 1;goto _again;} } break; case 15: -/* #line 255 "user/ansi_parser.rl" */ +/* #line 322 "user/ansi_parser.rl" */ { - apars_handle_setXCtrls((*p)); + apars_handle_setXCtrls((*p)); // weird control settings like 7 bit / 8 bit mode {cs = 1;goto _again;} } break; case 16: -/* #line 260 "user/ansi_parser.rl" */ +/* #line 327 "user/ansi_parser.rl" */ { // abuse the buffer for storing the leading char osc_buffer[0] = (*p); @@ -590,13 +657,13 @@ execFuncs: } break; case 17: -/* #line 266 "user/ansi_parser.rl" */ +/* #line 333 "user/ansi_parser.rl" */ { apars_handle_characterSet(osc_buffer[0], (*p)); {cs = 1;goto _again;} } break; -/* #line 600 "user/ansi_parser.c" */ +/* #line 667 "user/ansi_parser.c" */ } } goto _again; @@ -614,7 +681,7 @@ _again: while ( __nacts-- > 0 ) { switch ( *__acts++ ) { case 6: -/* #line 159 "user/ansi_parser.rl" */ +/* #line 220 "user/ansi_parser.rl" */ { ansi_warn("Invalid escape sequence discarded."); apars_handle_badseq(); @@ -623,7 +690,7 @@ _again: goto _again;} } break; -/* #line 627 "user/ansi_parser.c" */ +/* #line 694 "user/ansi_parser.c" */ } } } @@ -631,7 +698,7 @@ goto _again;} _out: {} } -/* #line 290 "user/ansi_parser.rl" */ +/* #line 357 "user/ansi_parser.rl" */ } diff --git a/user/ansi_parser.h b/user/ansi_parser.h index 674587f..c922986 100644 --- a/user/ansi_parser.h +++ b/user/ansi_parser.h @@ -18,6 +18,7 @@ extern void apars_handle_hashCode(char c); extern void apars_handle_characterSet(char leadchar, char c); extern void apars_handle_setXCtrls(char c); extern void apars_reset_utf8buffer(void); +extern void apars_handle_bel(void); void ansi_parser_reset(void); @@ -43,10 +44,9 @@ extern volatile u32 ansi_parser_char_cnt; * \attention -> but always check the Ragel output for 'p--' * or 'p -=', that means trouble. * - * \param newdata - array of new chars to process - * \param len - length of the newdata buffer + * \param newchar - received char */ -void ansi_parser(const char *newdata, size_t len); +void ansi_parser(char newchar); /** This shows a short error message and prints the history (if any) */ void apars_handle_badseq(void); diff --git a/user/ansi_parser.rl b/user/ansi_parser.rl index 9797e1b..45b481c 100644 --- a/user/ansi_parser.rl +++ b/user/ansi_parser.rl @@ -1,6 +1,8 @@ #include #include "ansi_parser.h" #include "screen.h" +#include "ascii.h" +#include "uart_driver.h" /* Ragel constants block */ %%{ @@ -9,6 +11,7 @@ }%% static volatile int cs = -1; +static volatile bool inside_osc = false; volatile u32 ansi_parser_char_cnt = 0; @@ -16,6 +19,7 @@ void ICACHE_FLASH_ATTR ansi_parser_reset(void) { if (cs != ansi_start) { cs = ansi_start; + inside_osc = false; apars_reset_utf8buffer(); ansi_warn("Parser timeout, state reset"); } @@ -63,7 +67,7 @@ apars_handle_badseq(void) * \param len - length of the newdata buffer */ void ICACHE_FLASH_ATTR -ansi_parser(const char *newdata, size_t len) +ansi_parser(char newchar) { // The CSI code is built here static char csi_leading; //!< Leading char, 0 if none @@ -72,32 +76,89 @@ ansi_parser(const char *newdata, size_t len) static int csi_n[CSI_N_MAX]; //!< Param digits static char csi_char; //!< CSI action char (end) static char osc_buffer[OSC_CHAR_MAX]; - static int osc_bi; + static int osc_bi; // buffer char index + // This is used to detect timeout delay (time since last rx char) ansi_parser_char_cnt++; - if (len == 0) len = strlen(newdata); - - // Load new data to Ragel vars - const char *p = newdata; - const char *eof = NULL; - const char *pe = newdata + len; - // Init Ragel on the first run if (cs == -1) { %% write init; -#if DEBUG_ANSI - memset(history, 0, sizeof(history)); -#endif + #if DEBUG_ANSI + memset(history, 0, sizeof(history)); + #endif } -#if DEBUG_ANSI - for(int i=len; i= ' ' + + // bypass the parser for simple characters (speed-up) + if (cs == ansi_start) { + apars_handle_plainchar(newchar); + return; + } } - strcpy(&history[HISTORY_LEN-len], newdata); -#endif + + // Load new data to Ragel vars + const char *p = &newchar; + const char *eof = NULL; + const char *pe = &newchar + 1; // The parser %%{ @@ -185,6 +246,8 @@ ansi_parser(const char *newdata, size_t len) osc_bi = 0; osc_buffer[0] = '\0'; + inside_osc = true; + fgoto OSC_body; } @@ -192,11 +255,13 @@ ansi_parser(const char *newdata, size_t len) action SetTitle_start { osc_bi = 0; osc_buffer[0] = '\0'; + inside_osc = true; fgoto TITLE_body; } action OSC_resize { apars_handle_OSC_SetScreenSize(csi_n[0], csi_n[1]); + inside_osc = false; fgoto main; } @@ -207,12 +272,14 @@ ansi_parser(const char *newdata, size_t len) action OSC_title { osc_buffer[osc_bi++] = '\0'; apars_handle_OSC_SetTitle(osc_buffer); + inside_osc = false; fgoto main; } action OSC_button { osc_buffer[osc_bi++] = '\0'; apars_handle_OSC_SetButton(csi_n[0], osc_buffer); + inside_osc = false; fgoto main; } @@ -253,7 +320,7 @@ ansi_parser(const char *newdata, size_t len) } action SetXCtrls { - apars_handle_setXCtrls(fc); + apars_handle_setXCtrls(fc); // weird control settings like 7 bit / 8 bit mode fgoto main; } diff --git a/user/ansi_parser_callbacks.c b/user/ansi_parser_callbacks.c index b67bfd5..4801b0f 100644 --- a/user/ansi_parser_callbacks.c +++ b/user/ansi_parser_callbacks.c @@ -22,8 +22,6 @@ static int utf_j = 0; void ICACHE_FLASH_ATTR apars_handle_plainchar(char c) { - if (c == 7) return; // BELL - beep (TODO play beep in browser) - // collecting unicode glyphs... if (c & 0x80) { if (utf_i == 0) { @@ -64,17 +62,6 @@ apars_handle_plainchar(char c) } } else { - if (c == 14) { - // ShiftIN - screen_set_charset_n(1); - return; - } - if (c == 15) { - // ShiftOUT - screen_set_charset_n(0); - return; - } - utf_collect[0] = c; utf_collect[1] = 0; // just to make sure it's closed... screen_putchar(utf_collect); @@ -102,6 +89,7 @@ apars_handle_characterSet(char leadchar, char c) // other alternatives * + . - / not implemented } +/** ESC SP */ void ICACHE_FLASH_ATTR apars_handle_setXCtrls(char c) { @@ -109,6 +97,12 @@ apars_handle_setXCtrls(char c) // ansi_warn("NOIMPL Select %cbit ctrls", c=='F'? '7':'8'); } +void ICACHE_FLASH_ATTR +apars_handle_bel(void) +{ + // TODO pass to the browser somehow +} + /** * \brief Handle fully received CSI ANSI sequence * \param leadchar - private range leading character, 0 if none @@ -402,11 +396,11 @@ void ICACHE_FLASH_ATTR apars_handle_shortCode(char c) screen_reset(); break; - case '7': // save cursor + attrs + case '7': // save cursor + attributes screen_cursor_save(true); break; - case '8': // restore cursor + attrs + case '8': // restore cursor + attributes screen_cursor_restore(true); break; diff --git a/user/ansi_parser_callbacks.h b/user/ansi_parser_callbacks.h index c0101f1..3126695 100644 --- a/user/ansi_parser_callbacks.h +++ b/user/ansi_parser_callbacks.h @@ -1,6 +1,8 @@ #ifndef ANSI_PARSER_CALLBACKS_H #define ANSI_PARSER_CALLBACKS_H +#include "screen.h" + void apars_handle_plainchar(char c); void apars_handle_CSI(char leadchar, int *params, int count, char keychar); void apars_handle_OSC_SetScreenSize(int rows, int cols); @@ -11,5 +13,6 @@ void apars_handle_hashCode(char c); void apars_handle_characterSet(char leadchar, char c); void apars_handle_setXCtrls(char c); void apars_reset_utf8buffer(void); +void apars_handle_bel(void); #endif //ESP_VT100_FIRMWARE_ANSI_PARSER_CALLBACKS_H diff --git a/user/ascii.h b/user/ascii.h new file mode 100644 index 0000000..a0deec3 --- /dev/null +++ b/user/ascii.h @@ -0,0 +1,45 @@ +// +// Created by MightyPork on 2017/08/19. +// + +#ifndef ESP_VT100_FIRMWARE_ASCII_H +#define ESP_VT100_FIRMWARE_ASCII_H + +enum ASCII_CODES { + NUL = 0, + SOH = 1, + STX = 2, + ETX = 3, + EOT = 4, + ENQ = 5, + ACK = 6, + BEL = 7, + BS = 8, + TAB = 9, + LF = 10, + VT = 11, + FF = 12, + CR = 13, + SO = 14, + SI = 15, + DLE = 16, + DC1 = 17, + DC2 = 18, + DC3 = 19, + DC4 = 20, + NAK = 21, + SYN = 22, + ETB = 23, + CAN = 24, + EM = 25, + SUB = 26, + ESC = 27, + FS = 28, + GS = 29, + RS = 30, + US = 31, + SP = 32, + DEL = 127, +}; + +#endif //ESP_VT100_FIRMWARE_ASCII_H diff --git a/user/serial.c b/user/serial.c index 0f2cd2d..8349788 100644 --- a/user/serial.c +++ b/user/serial.c @@ -42,5 +42,5 @@ void ICACHE_FLASH_ATTR serialInit(void) */ void ICACHE_FLASH_ATTR UART_HandleRxByte(char c) { - ansi_parser(&c, 1); + ansi_parser(c); }