Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
espterm.cpp
00001 #include "mbed.h" 00002 #include "espterm.hpp" 00003 00004 #include <cstdarg> 00005 00006 00007 void ESPTerm::init(Serial *s) 00008 { 00009 cs = -1; 00010 device_ok = false; 00011 00012 on_mouse = NULL; 00013 on_button = NULL; 00014 on_key = NULL; 00015 on_esp_reset = NULL; 00016 on_char_rx = NULL; 00017 on_osc_rx = NULL; 00018 00019 ser = s; 00020 ser->attach(callback(this, &ESPTerm::ser_rx_char), Serial::RxIrq); 00021 } 00022 00023 00024 ESPTerm::ESPTerm(Serial *s) 00025 { 00026 init(s); 00027 } 00028 00029 00030 ESPTerm::ESPTerm(void) 00031 { 00032 // Defaults 00033 init(new Serial(PA_2, PA_3, 115200)); 00034 } 00035 00036 00037 ESPTerm::ESPTerm(PinName txPin, PinName rxPin, int baud) 00038 { 00039 init(new Serial(txPin, rxPin, baud)); 00040 } 00041 00042 00043 // ----- Printing ----- 00044 00045 00046 int ESPTerm::printf(const char *format, ...) 00047 { 00048 std::va_list arg; 00049 va_start(arg, format); 00050 int r = ser->vprintf(format, arg); 00051 va_end(arg); 00052 00053 return r; 00054 } 00055 00056 00057 // alias of printf 00058 int ESPTerm::print(const char *format, ...) 00059 { 00060 std::va_list arg; 00061 va_start(arg, format); 00062 int r = ser->vprintf(format, arg); 00063 va_end(arg); 00064 00065 return r; 00066 } 00067 00068 00069 int ESPTerm::println(const char *format, ...) { 00070 std::va_list arg; 00071 va_start(arg, format); 00072 int r = ser->vprintf(format, arg); 00073 va_end(arg); 00074 00075 r += ser->puts("\r\n"); 00076 return r; 00077 } 00078 00079 00080 // ----- Colors ----- 00081 00082 00083 void ESPTerm::fg(Color c) 00084 { 00085 int ci = c; 00086 if(ci > 7) { 00087 ci += (90-8); 00088 } else { 00089 ci += 30; 00090 } 00091 ser->printf("\033[%dm", ci); 00092 } 00093 00094 00095 void ESPTerm::bg(Color c) 00096 { 00097 int ci = c; 00098 if(ci > 7) { 00099 ci += (100-8); 00100 } else { 00101 ci += 40; 00102 } 00103 ser->printf("\033[%dm", ci); 00104 } 00105 00106 00107 void ESPTerm::reset_attribs(void) 00108 { 00109 ser->puts("\033[0m"); 00110 } 00111 00112 00113 // ----- Cursor control & erasing ----- 00114 00115 00116 void ESPTerm::go_to(int y, int x) 00117 { 00118 ser->printf("\033[%d;%dH", y, x); 00119 } 00120 00121 00122 void ESPTerm::move(int dy, int dx) 00123 { 00124 if (dy != 0) { 00125 if (dy > 0) { 00126 // Down 00127 ser->printf("\033[%dB", dy); 00128 } 00129 else { 00130 // Up 00131 ser->printf("\033[%dA", -dy); 00132 } 00133 } 00134 00135 if (dx != 0) { 00136 if (dx > 0) { 00137 // Forward 00138 ser->printf("\033[%dC", dx); 00139 } 00140 else { 00141 // Backward 00142 ser->printf("\033[%dD", -dx); 00143 } 00144 } 00145 } 00146 00147 00148 void ESPTerm::clear_screen(ClearMode mode) 00149 { 00150 ser->printf("\033[%dJ", mode); 00151 } 00152 00153 00154 void ESPTerm::clear_line(ClearMode mode) 00155 { 00156 ser->printf("\033[%dK", mode); 00157 } 00158 00159 00160 void ESPTerm::screen_reset(void) 00161 { 00162 ser->puts("\033c"); 00163 } 00164 00165 00166 void ESPTerm::show_cursor(bool yes) 00167 { 00168 if (yes) { 00169 ser->puts("\033[?25h"); 00170 } 00171 else { 00172 ser->puts("\033[?25l"); 00173 } 00174 } 00175 00176 00177 void ESPTerm::scroll(int lines) 00178 { 00179 if (lines > 0) { 00180 ser->printf("\033[%dT", lines); 00181 } 00182 else { 00183 ser->printf("\033[%dS", -lines); 00184 } 00185 } 00186 00187 00188 void ESPTerm::cursor_push(bool with_attribs) 00189 { 00190 if (with_attribs) { 00191 ser->puts("\0337"); 00192 } 00193 else { 00194 ser->puts("\033[s"); 00195 } 00196 } 00197 00198 00199 void ESPTerm::cursor_pop(bool with_attribs) 00200 { 00201 if (with_attribs) { 00202 ser->puts("\0338"); 00203 } 00204 else { 00205 ser->puts("\033[u"); 00206 } 00207 } 00208 00209 00210 void ESPTerm::wrap_enable(bool yes) 00211 { 00212 if (yes) { 00213 ser->puts("\033[?7h"); 00214 } 00215 else { 00216 ser->puts("\033[?7l"); 00217 } 00218 } 00219 00220 00221 // ----- System commands ----- 00222 00223 00224 void ESPTerm::factory_reset(void) 00225 { 00226 ser->puts("\033]FR\a"); 00227 } 00228 00229 00230 void ESPTerm::set_screen_size(int rows, int cols) 00231 { 00232 ser->printf("\033]W%d;%d\a", rows, cols); 00233 } 00234 00235 00236 bool ESPTerm::query_status(void) 00237 { 00238 if (device_ok) return true; 00239 00240 ser->puts("\033[5n"); 00241 return false; 00242 } 00243 00244 00245 // ----- Rx command parsing ----- 00246 00247 00248 void ESPTerm::ser_rx_char(void) 00249 { 00250 while (ser->readable()) { 00251 char c = ser->getc(); 00252 ansi_parser(&c, 1); // pretend as if it was a string, this is safe 00253 } 00254 } 00255 00256 00257 void ESPTerm::apars_handle_plainchar(char c) 00258 { 00259 if (c == 24) { 00260 if (on_esp_reset) on_esp_reset(); 00261 } 00262 else if (c >= 1 && c <= 5) { 00263 if (on_button) on_button((int)c); 00264 } 00265 else { 00266 if (on_char_rx) on_char_rx(c); 00267 } 00268 } 00269 00270 00271 void ESPTerm::apars_handle_csi(char lead, const int* nums, char keychar) 00272 { 00273 // Keyboard events 00274 if (on_key) { 00275 if (keychar == 'A') on_key(KEY_UP); 00276 else if (keychar == 'B') on_key(KEY_DOWN); 00277 else if (keychar == 'C') on_key(KEY_RIGHT); 00278 else if (keychar == 'D') on_key(KEY_LEFT); 00279 } 00280 00281 // Screen tapped / clicked 00282 if (on_mouse && keychar == 'M') { 00283 on_mouse(nums[0], nums[1], (MouseEvent) nums[2]); 00284 } 00285 00286 // "Device OK" response to "Device Status Query" 00287 if (keychar == 'n' && nums[0] == 0) { 00288 device_ok = true; 00289 } 00290 00291 // ... other commands when added 00292 } 00293 00294 00295 void ESPTerm::apars_handle_osc(const char *str) 00296 { 00297 // ... additional parsing when needed in later esp term versions 00298 if (on_osc_rx) on_osc_rx(str); 00299 } 00300 00301 00302 void ESPTerm::apars_handle_badseq(void) 00303 { 00304 // Do nothing 00305 } 00306 00307 00308 00309 /* ----- Ragel constants block ------ */ 00310 00311 /* #line 38 "ansi_parser_cpp.c" */ 00312 static const int ansi_start = 1; 00313 //static const int ansi_first_final = 7; 00314 //static const int ansi_error = 0; 00315 00316 //static const int ansi_en_CSI_body = 3; 00317 //static const int ansi_en_OSC_body = 5; 00318 //static const int ansi_en_main = 1; 00319 00320 00321 00322 /* Ragel generated parser */ 00323 00324 /** 00325 * \brief Linear ANSI chars stream parser (Rage generated) 00326 * 00327 * Parses a stream of bytes using a Ragel parser. The defined 00328 * grammar does not use 'unget', so the entire buffer is 00329 * always processed in a linear manner. 00330 * 00331 * \attention -> but always check the Ragel output for 'p--' 00332 * or 'p -=', that means trouble. 00333 * 00334 * \param newdata - array of new chars to process 00335 * \param len - length of the newdata buffer 00336 */ 00337 void ESPTerm::ansi_parser(const char *newdata, size_t len) 00338 { 00339 if (len == 0) len = strlen(newdata); 00340 00341 // Load new data to Ragel vars 00342 const char *p = newdata; 00343 const char *eof = NULL; 00344 const char *pe = newdata + len; 00345 00346 // Init Ragel on the first run 00347 if (cs == -1) { 00348 00349 /* #line 77 "ansi_parser_cpp.c" */ 00350 { 00351 cs = ansi_start; 00352 } 00353 00354 /* #line 65 "ansi_parser_cpp.rl" */ 00355 } 00356 00357 // The parser 00358 00359 /* #line 87 "ansi_parser_cpp.c" */ 00360 { 00361 if ( p == pe ) 00362 goto _test_eof; 00363 switch ( cs ) 00364 { 00365 tr0: 00366 /* #line 75 "ansi_parser_cpp.rl" */ 00367 { 00368 apars_handle_plainchar((*p)); 00369 } 00370 goto st1; 00371 st1: 00372 if ( ++p == pe ) 00373 goto _test_eof1; 00374 case 1: 00375 /* #line 103 "ansi_parser_cpp.c" */ 00376 if ( (*p) == 27 ) 00377 goto st2; 00378 goto tr0; 00379 st2: 00380 if ( ++p == pe ) 00381 goto _test_eof2; 00382 case 2: 00383 switch( (*p) ) { 00384 case 91: goto tr3; 00385 case 93: goto tr4; 00386 } 00387 goto tr2; 00388 tr2: 00389 /* #line 116 "ansi_parser_cpp.rl" */ 00390 { 00391 apars_handle_badseq(); 00392 {goto st1;} 00393 } 00394 // goto st0; 00395 /* #line 123 "ansi_parser_cpp.c" */ 00396 //st0: 00397 //cs = 0; 00398 // goto _out; 00399 tr3: 00400 /* #line 82 "ansi_parser_cpp.rl" */ 00401 { 00402 /* Reset the CSI builder */ 00403 csi_leading = csi_char = 0; 00404 csi_ni = 0; 00405 00406 /* Zero out digits */ 00407 for(int i = 0; i < CSI_N_MAX; i++) { 00408 csi_n[i] = 0; 00409 } 00410 00411 {goto st3;} 00412 } 00413 //goto st7; 00414 tr4: 00415 /* #line 129 "ansi_parser_cpp.rl" */ 00416 { 00417 /* Reset the OSC buffer */ 00418 osc_i = 0; 00419 {goto st5;} 00420 } 00421 //goto st7; 00422 //st7: 00423 // if ( ++p == pe ) 00424 // goto _test_eof7; 00425 case 7: 00426 /* #line 154 "ansi_parser_cpp.c" */ 00427 if ( (*p) == 27 ) 00428 goto st2; 00429 goto tr0; 00430 st3: 00431 if ( ++p == pe ) 00432 goto _test_eof3; 00433 case 3: 00434 if ( (*p) == 59 ) 00435 goto tr7; 00436 if ( (*p) < 60 ) { 00437 if ( (*p) > 47 ) { 00438 if ( 48 <= (*p) && (*p) <= 57 ) 00439 goto tr6; 00440 } else if ( (*p) >= 32 ) 00441 goto tr5; 00442 } else if ( (*p) > 64 ) { 00443 if ( (*p) > 90 ) { 00444 if ( 97 <= (*p) && (*p) <= 122 ) 00445 goto tr8; 00446 } else if ( (*p) >= 65 ) 00447 goto tr8; 00448 } else 00449 goto tr5; 00450 goto tr2; 00451 tr5: 00452 /* #line 95 "ansi_parser_cpp.rl" */ 00453 { 00454 csi_leading = (*p); 00455 } 00456 goto st4; 00457 tr6: 00458 /* #line 99 "ansi_parser_cpp.rl" */ 00459 { 00460 /* x10 + digit */ 00461 if (csi_ni < CSI_N_MAX) { 00462 csi_n[csi_ni] = csi_n[csi_ni]*10 + ((*p) - '0'); 00463 } 00464 } 00465 goto st4; 00466 tr7: 00467 /* #line 106 "ansi_parser_cpp.rl" */ 00468 { 00469 csi_ni++; 00470 } 00471 goto st4; 00472 st4: 00473 if ( ++p == pe ) 00474 goto _test_eof4; 00475 case 4: 00476 /* #line 204 "ansi_parser_cpp.c" */ 00477 if ( (*p) == 59 ) 00478 goto tr7; 00479 if ( (*p) < 65 ) { 00480 if ( 48 <= (*p) && (*p) <= 57 ) 00481 goto tr6; 00482 } else if ( (*p) > 90 ) { 00483 if ( 97 <= (*p) && (*p) <= 122 ) 00484 goto tr8; 00485 } else 00486 goto tr8; 00487 goto tr2; 00488 tr8: 00489 /* #line 110 "ansi_parser_cpp.rl" */ 00490 { 00491 csi_char = (*p); 00492 apars_handle_csi(csi_leading, csi_n, csi_char); 00493 {goto st1;} 00494 } 00495 // goto st8; 00496 //st8: 00497 // if ( ++p == pe ) 00498 // goto _test_eof8; 00499 case 8: 00500 /* #line 228 "ansi_parser_cpp.c" */ 00501 goto tr2; 00502 tr9: 00503 /* #line 135 "ansi_parser_cpp.rl" */ 00504 { 00505 if (osc_i < OSC_BUF_LEN-1) { 00506 osc_buff[osc_i++] = (*p); 00507 } 00508 } 00509 goto st5; 00510 st5: 00511 if ( ++p == pe ) 00512 goto _test_eof5; 00513 case 5: 00514 /* #line 242 "ansi_parser_cpp.c" */ 00515 switch( (*p) ) { 00516 case 7: goto tr10; 00517 case 27: goto st6; 00518 } 00519 goto tr9; 00520 tr10: 00521 /* #line 141 "ansi_parser_cpp.rl" */ 00522 { 00523 /** Terminate the buffer */ 00524 osc_buff[osc_i] = '\0'; 00525 apars_handle_osc(osc_buff); 00526 00527 {goto st1;} 00528 } 00529 // goto st9; 00530 //st9: 00531 // if ( ++p == pe ) 00532 // goto _test_eof9; 00533 case 9: 00534 /* #line 262 "ansi_parser_cpp.c" */ 00535 goto tr2; 00536 st6: 00537 if ( ++p == pe ) 00538 goto _test_eof6; 00539 case 6: 00540 if ( (*p) == 92 ) 00541 goto tr10; 00542 goto tr2; 00543 } 00544 _test_eof1: cs = 1; goto _test_eof; 00545 _test_eof2: cs = 2; goto _test_eof; 00546 //_test_eof7: cs = 7; goto _test_eof; 00547 _test_eof3: cs = 3; goto _test_eof; 00548 _test_eof4: cs = 4; goto _test_eof; 00549 //_test_eof8: cs = 8; goto _test_eof; 00550 _test_eof5: cs = 5; goto _test_eof; 00551 //_test_eof9: cs = 9; goto _test_eof; 00552 _test_eof6: cs = 6; goto _test_eof; 00553 00554 _test_eof: {} 00555 if ( p == eof ) 00556 { 00557 switch ( cs ) { 00558 case 1: 00559 case 2: 00560 case 3: 00561 case 4: 00562 case 5: 00563 case 6: 00564 /* #line 116 "ansi_parser_cpp.rl" */ 00565 { 00566 apars_handle_badseq(); 00567 {goto st1;} 00568 } 00569 // break; 00570 /* #line 298 "ansi_parser_cpp.c" */ 00571 } 00572 } 00573 00574 //_out: {} 00575 } 00576 00577 /* #line 162 "ansi_parser_cpp.rl" */ 00578 00579 } 00580 00581 00582 00583 00584 00585 00586 00587 00588 00589 00590 00591 00592 00593 00594 00595 00596 00597 00598 00599
Generated on Fri Jul 15 2022 15:31:59 by
1.7.2