From 467f300b3d8c7f817daaf74731acf988d6e8ce01 Mon Sep 17 00:00:00 2001 From: DiSlord Live Date: Sat, 3 Dec 2022 12:50:26 +0300 Subject: [PATCH] Add *.cmd files browse and execute Added some useful functions --- main.c | 76 ++++++++++++++++++++++++++++++++------------------- nanovna.h | 4 ++- ui.c | 26 +++++++----------- vna_browser.c | 42 ++++++++++++++-------------- 4 files changed, 81 insertions(+), 67 deletions(-) diff --git a/main.c b/main.c index 6b15c21..f151edf 100644 --- a/main.c +++ b/main.c @@ -2314,37 +2314,48 @@ static void shell_init_connection(void){ bool global_abort = false; -static const VNAShellCommand *VNAShell_parceLine(char *line){ - // Parse and execute line - char *lp = line, *ep; - shell_nargs = 0; - shell_args[0] = line; // shell_args[0] is used in error message, must be initialized -// DEBUG_LOG(0, lp); // debug console log - while (*lp != 0) { - // Skipping white space and tabs at string begin. - while (*lp == ' ' || *lp == '\t') lp++; - // If an argument starts with a double quote then its delimiter is another quote, else - // delimiter is white space. - ep = (*lp == '"') ? strpbrk(++lp, "\"") : strpbrk(lp, " \t"); - // Store in args string - shell_args[shell_nargs++] = lp; - // Stop, end of input string - if ((lp = ep) == NULL) break; - // Argument limits check - if (shell_nargs > VNA_SHELL_MAX_ARGUMENTS) { - shell_printf("too many arguments, max " define_to_STR(VNA_SHELL_MAX_ARGUMENTS) "" VNA_SHELL_NEWLINE_STR); - return NULL; +static inline char* vna_strpbrk(char *s1, const char *s2) { + do { + const char *s = s2; + do { + if (*s == *s1) return s1; + s++; + } while (*s); + s1++; + } while(*s1); + return s1; +} + +/* + * Split line by arguments, return arguments count + */ +int parse_line(char *line, char* args[], int max_cnt) { + char *lp = line, c; + const char *brk; + uint16_t nargs = 0; + while ((c = *lp) != 0) { // While not end + if (c != ' ' && c != '\t') { // Skipping white space and tabs. + if (c == '"') {lp++; brk = "\""; } // string end is next quote or end + else { brk = " \t";} // string end is tab or space or end + if (nargs < max_cnt) args[nargs] = lp; // Put pointer in args buffer (if possible) + nargs++; // Substring count + lp = vna_strpbrk(lp, brk); // search end + if (*lp == 0) break; // Stop, end of input string + *lp = 0; // Set zero at the end of substring } - // Set zero at the end of string and continue check - *lp++ = 0; + lp++; } - if (shell_nargs){ - if (shell_args[0][0] == '.') { - global_abort = true; - return NULL; - } - global_abort = false; + return nargs; +} +static const VNAShellCommand *VNAShell_parceLine(char *line){ + // Parse and execute line + shell_nargs = parse_line(line, shell_args, ARRAY_COUNT(shell_args)); + if (shell_nargs > ARRAY_COUNT(shell_args)) { + shell_printf("too many arguments, max " define_to_STR(VNA_SHELL_MAX_ARGUMENTS) "" VNA_SHELL_NEWLINE_STR); + return NULL; + } + if (shell_nargs > 0) { const VNAShellCommand *scp; for (scp = commands; scp->sc_name != NULL; scp++) if (get_str_index(scp->sc_name, shell_args[0]) == 0) @@ -2417,6 +2428,15 @@ static void VNAShell_executeLine(char *line) shell_printf("%s?" VNA_SHELL_NEWLINE_STR, shell_args[0]); } +void shell_executeCMDLine(char *line) { + // Disable shell output (not allow shell_printf write, but not block other output!!) + shell_stream = NULL; + const VNAShellCommand *scp = VNAShell_parceLine(line); + if (scp && (scp->flags & CMD_RUN_IN_LOAD)) + scp->sc_function(shell_nargs - 1, &shell_args[1]); + PREPARE_STREAM; +} + #ifdef __SD_CARD_LOAD__ #ifndef __USE_SD_CARD__ #error "Need enable SD card support __USE_SD_CARD__ in nanovna.h, for use ENABLE_SD_CARD_CMD" diff --git a/nanovna.h b/nanovna.h index a4239c6..226508d 100644 --- a/nanovna.h +++ b/nanovna.h @@ -90,7 +90,7 @@ #define __ULTRA__ #define __USE_RTC__ // Enable RTC clock #define __USE_SD_CARD__ // Enable SD card support -#define __SD_CARD_LOAD__ // Allow run commands from SD card (config.ini in root) +//#define __SD_CARD_LOAD__ // Allow run commands from SD card (config.ini in root), if enabled __SD_FILE_BROWSER__ scripts run from *.cmd in it #define __SD_CARD_DUMP_FIRMWARE__ // Allow dump firmware to SD card #define __SD_FILE_BROWSER__ #define __LCD_BRIGHTNESS__ // LCD or hardware allow change brightness, add menu item for this @@ -829,6 +829,7 @@ extern void clear_marker_cache(void); void shell_update_speed(void); void shell_reset_console(void); int shell_serial_printf(const char *fmt, ...); +void shell_executeCMDLine(char *line); // marker enum { @@ -1646,6 +1647,7 @@ typedef struct { /* * misclinous */ +int parse_line(char *line, char* args[], int max_cnt); int plot_printf(char *str, int, const char *fmt, ...); #define PULSE do { palClearPad(GPIOC, GPIOC_LED); palSetPad(GPIOC, GPIOC_LED);} while(0) //extern int setting_attenuate; diff --git a/ui.c b/ui.c index 8b83c7f..a946555 100644 --- a/ui.c +++ b/ui.c @@ -3566,9 +3566,7 @@ enum { #ifdef __SD_CARD_DUMP_FIRMWARE__ FMT_BIN_FILE, #endif -//#ifdef __SD_CARD_LOAD__ -// FMT_CMD_FILE, -//#endif + FMT_CMD_FILE, FMT_CFG_FILE, FMT_PRS_FILE, }; @@ -3580,9 +3578,7 @@ static const char *file_ext[] = { #ifdef __SD_CARD_DUMP_FIRMWARE__ [FMT_BIN_FILE] = "bin", #endif -//#ifdef __SD_CARD_LOAD__ -// [FMT_CMD_FILE] = "cmd", -//#endif + [FMT_CMD_FILE] = "cmd", [FMT_CFG_FILE] = "cfg", [FMT_PRS_FILE] = "prs", }; @@ -4099,6 +4095,13 @@ static const menuitem_t menu_settings[] = #ifdef __NOISE_FIGURE__ { MT_KEYPAD, KM_NF, "NF\n\b%s", "Enter tinySA noise figure"}, #endif +#ifdef __SD_CARD_DUMP_FIRMWARE__ + { MT_CALLBACK, FMT_BIN_FILE, "DUMP\nFIRMWARE", menu_sdcard_cb}, +#endif +#ifdef __SD_CARD_LOAD__ + { MT_CALLBACK, 0 , "LOAD\nCONFIG.INI", menu_load_config_cb}, +// { MT_CALLBACK, 1 , "LOAD\nSETTING.INI", menu_load_config_cb}, +#endif #ifdef TINYSA4 { MT_ADV_CALLBACK, 0, "INTERNALS", menu_internals_acb}, #endif @@ -4380,20 +4383,11 @@ static const menuitem_t menu_stimulus[] = { #ifdef __USE_SD_CARD__ static const menuitem_t menu_storage[] = { -#ifdef __SD_CARD_LOAD__ - { MT_CALLBACK, 0 , "LOAD\nCONFIG.INI", menu_load_config_cb}, -// { MT_CALLBACK, 1 , "LOAD\nSETTING.INI", menu_load_config_cb}, -#endif -#ifdef __USE_SD_CARD__ -#ifdef __SD_CARD_DUMP_FIRMWARE__ - { MT_CALLBACK, FMT_BIN_FILE, "DUMP\nFIRMWARE", menu_sdcard_cb}, -#endif #ifdef __SD_FILE_BROWSER__ { MT_CALLBACK, FMT_BMP_FILE, "LOAD BMP", menu_sdcard_browse_cb }, + { MT_CALLBACK, FMT_CMD_FILE, "LOAD CMD", menu_sdcard_browse_cb }, #endif - { MT_ADV_CALLBACK, 0, "AUTO NAME", menu_autoname_acb }, -#endif { MT_NONE, 0, NULL, menu_back} // next-> menu_back }; #endif diff --git a/vna_browser.c b/vna_browser.c index 15f192c..48cc809 100644 --- a/vna_browser.c +++ b/vna_browser.c @@ -113,28 +113,26 @@ repeat: ili9341_set_foreground(LCD_FG_COLOR); ili9341_set_background(LCD_BG_COLOR); switch (keypad_mode) { -//#ifdef __SD_CARD_LOAD__ -// case FMT_CMD_FILE: -// { -// const int buffer_size = 256; -// const int line_size = 128; -// char *buf_8 = (char *)spi_buffer; // must be greater then buffer_size + line_size -// char *line = buf_8 + buffer_size; -// uint16_t j = 0, i; -// while (f_read(fs_file, buf_8, buffer_size, &size) == FR_OK && size > 0) { -// for (i = 0; i < size; i++) { -// uint8_t c = buf_8[i]; -// if (c == '\r') { // New line (Enter) -// line[j] = 0; j = 0; -// VNAShell_executeCMDLine(line); -// } -// else if (c < 0x20) continue; // Others (skip) -// else if (j < line_size) line[j++] = (char)c; // Store -// } -// } -// break; -// } -//#endif + case FMT_CMD_FILE: + { + const int buffer_size = 256; + const int line_size = 128; + char *buf_8 = (char *)spi_buffer; // must be greater then buffer_size + line_size + char *line = buf_8 + buffer_size; + uint16_t j = 0, i; + while (f_read(fs_file, buf_8, buffer_size, &size) == FR_OK && size > 0) { + for (i = 0; i < size; i++) { + uint8_t c = buf_8[i]; + if (c == '\r') { // New line (Enter) + line[j] = 0; j = 0; + shell_executeCMDLine(line); + } + else if (c < 0x20) continue; // Others (skip) + else if (j < line_size) line[j++] = (char)c; // Store + } + } + break; + } /* * BMP file load procedure, load only device screenshots */