From 7f97e8538f2ea19efa91899d42bc4ee80a623656 Mon Sep 17 00:00:00 2001 From: whowechina Date: Sat, 18 May 2024 14:15:25 +0800 Subject: [PATCH] Put build time in help --- Production/firmware/mai_pico.uf2 | Bin 148480 -> 148480 bytes firmware/src/cli.c | 387 ++++++++++++++++--------------- 2 files changed, 194 insertions(+), 193 deletions(-) diff --git a/Production/firmware/mai_pico.uf2 b/Production/firmware/mai_pico.uf2 index 9701b20f451540cd6f2f9658e5306329531453fd..037319011479c5b476b0df93af011be3f2432d80 100644 GIT binary patch delta 14440 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 diff --git a/firmware/src/cli.c b/firmware/src/cli.c index 0c9792c..d30d28d 100644 --- a/firmware/src/cli.c +++ b/firmware/src/cli.c @@ -1,193 +1,194 @@ -#include -#include -#include -#include -#include - -#include "pico/stdio.h" -#include "pico/stdlib.h" -#include "pico/bootrom.h" -#include "cli.h" -#include "save.h" - -#define MAX_COMMANDS 32 -#define MAX_PARAMETERS 10 -#define MAX_PARAMETER_LENGTH 20 - -const char *cli_prompt = "cli>"; -const char *cli_logo = "CLI"; - -static const char *commands[MAX_COMMANDS]; -static const char *helps[MAX_COMMANDS]; -static cmd_handler_t handlers[MAX_COMMANDS]; -static int max_cmd_len = 0; - -static int num_commands = 0; - -void cli_register(const char *cmd, cmd_handler_t handler, const char *help) -{ - if (num_commands < MAX_COMMANDS) { - commands[num_commands] = cmd; - handlers[num_commands] = handler; - helps[num_commands] = help; - num_commands++; - if (strlen(cmd) > max_cmd_len) { - max_cmd_len = strlen(cmd); - } - } -} - -// return -1 if not matched, return -2 if ambiguous -int cli_match_prefix(const char *str[], int num, const char *prefix) -{ - int match = -1; - bool found = false; - - for (int i = 0; (i < num) && str[i]; i++) { - if (strncasecmp(str[i], prefix, strlen(prefix)) == 0) { - if (found) { - return -2; - } - found = true; - match = i; - } - } - - return match; -} - -static void handle_help(int argc, char *argv[]) -{ - printf("%s", cli_logo); - printf("\tSN: %016llx\n\n", board_id_64()); - printf("Available commands:\n"); - for (int i = 0; i < num_commands; i++) { - printf("%*s: %s\n", max_cmd_len + 2, commands[i], helps[i]); - } -} - -static int fps[2]; -void cli_fps_count(int core) -{ - static uint32_t last[2] = {0}; - static int counter[2] = {0}; - - counter[core]++; - - uint32_t now = time_us_32(); - if (now - last[core] < 1000000) { - return; - } - last[core] = now; - fps[core] = counter[core]; - counter[core] = 0; -} - -static void handle_fps(int argc, char *argv[]) -{ - printf("FPS: core 0: %d, core 1: %d\n", fps[0], fps[1]); -} - -static void handle_update(int argc, char *argv[]) -{ - printf("Boot into update mode.\n"); - fflush(stdout); - sleep_ms(100); - reset_usb_boot(0, 2); -} -int cli_extract_non_neg_int(const char *param, int len) -{ - if (len == 0) { - len = strlen(param); - } - int result = 0; - for (int i = 0; i < len; i++) { - if (!isdigit((uint8_t)param[i])) { - return -1; - } - result = result * 10 + param[i] - '0'; - } - return result; -} - -static char cmd_buf[256]; -static int cmd_len = 0; - -static void process_cmd() -{ - char *argv[MAX_PARAMETERS]; - int argc; - - char *cmd = strtok(cmd_buf, " \n"); - - if (strlen(cmd) == 0) { - return; - } - - argc = 0; - while ((argc < MAX_PARAMETERS) && - (argv[argc] = strtok(NULL, " ,\n")) != NULL) { - argc++; - } - - int match = cli_match_prefix(commands, num_commands, cmd); - if (match == -2) { - printf("Ambiguous command.\n"); - return; - } else if (match == -1) { - printf("Unknown command.\n"); - handle_help(0, NULL); - return; - } - - handlers[match](argc, argv); -} - -void cli_run() -{ - int c = getchar_timeout_us(0); - if (c == EOF) { - return; - } - - if (c == '\b' || c == 127) { // both backspace and delete - if (cmd_len > 0) { - cmd_len--; - printf("\b \b"); - } - return; - } - - if ((c != '\n') && (c != '\r')) { - - if (cmd_len < sizeof(cmd_buf) - 2) { - cmd_buf[cmd_len] = c; - printf("%c", c); - cmd_len++; - } - return; - } - - cmd_buf[cmd_len] = '\0'; - cmd_len = 0; - - printf("\n"); - - process_cmd(); - - printf(cli_prompt); -} - -void cli_init(const char *prompt, const char *logo) -{ - if (prompt) { - cli_prompt = prompt; - } - if (logo) { - cli_logo = logo; - } - - cli_register("?", handle_help, "Display this help message."); - cli_register("fps", handle_fps, "Display FPS."); - cli_register("update", handle_update, "Update firmware."); -} +#include +#include +#include +#include +#include + +#include "pico/stdio.h" +#include "pico/stdlib.h" +#include "pico/bootrom.h" +#include "cli.h" +#include "save.h" + +#define MAX_COMMANDS 32 +#define MAX_PARAMETERS 10 +#define MAX_PARAMETER_LENGTH 20 + +const char *cli_prompt = "cli>"; +const char *cli_logo = "CLI"; + +static const char *commands[MAX_COMMANDS]; +static const char *helps[MAX_COMMANDS]; +static cmd_handler_t handlers[MAX_COMMANDS]; +static int max_cmd_len = 0; + +static int num_commands = 0; + +void cli_register(const char *cmd, cmd_handler_t handler, const char *help) +{ + if (num_commands < MAX_COMMANDS) { + commands[num_commands] = cmd; + handlers[num_commands] = handler; + helps[num_commands] = help; + num_commands++; + if (strlen(cmd) > max_cmd_len) { + max_cmd_len = strlen(cmd); + } + } +} + +// return -1 if not matched, return -2 if ambiguous +int cli_match_prefix(const char *str[], int num, const char *prefix) +{ + int match = -1; + bool found = false; + + for (int i = 0; (i < num) && str[i]; i++) { + if (strncasecmp(str[i], prefix, strlen(prefix)) == 0) { + if (found) { + return -2; + } + found = true; + match = i; + } + } + + return match; +} + +static void handle_help(int argc, char *argv[]) +{ + printf("%s", cli_logo); + printf("\tSN: %016llx\n", board_id_64()); + printf("\tBuilt: %s %s\n\n", __DATE__, __TIME__); + printf("Available commands:\n"); + for (int i = 0; i < num_commands; i++) { + printf("%*s: %s\n", max_cmd_len + 2, commands[i], helps[i]); + } +} + +static int fps[2]; +void cli_fps_count(int core) +{ + static uint32_t last[2] = {0}; + static int counter[2] = {0}; + + counter[core]++; + + uint32_t now = time_us_32(); + if (now - last[core] < 1000000) { + return; + } + last[core] = now; + fps[core] = counter[core]; + counter[core] = 0; +} + +static void handle_fps(int argc, char *argv[]) +{ + printf("FPS: core 0: %d, core 1: %d\n", fps[0], fps[1]); +} + +static void handle_update(int argc, char *argv[]) +{ + printf("Boot into update mode.\n"); + fflush(stdout); + sleep_ms(100); + reset_usb_boot(0, 2); +} +int cli_extract_non_neg_int(const char *param, int len) +{ + if (len == 0) { + len = strlen(param); + } + int result = 0; + for (int i = 0; i < len; i++) { + if (!isdigit((uint8_t)param[i])) { + return -1; + } + result = result * 10 + param[i] - '0'; + } + return result; +} + +static char cmd_buf[256]; +static int cmd_len = 0; + +static void process_cmd() +{ + char *argv[MAX_PARAMETERS]; + int argc; + + char *cmd = strtok(cmd_buf, " \n"); + + if (strlen(cmd) == 0) { + return; + } + + argc = 0; + while ((argc < MAX_PARAMETERS) && + (argv[argc] = strtok(NULL, " ,\n")) != NULL) { + argc++; + } + + int match = cli_match_prefix(commands, num_commands, cmd); + if (match == -2) { + printf("Ambiguous command.\n"); + return; + } else if (match == -1) { + printf("Unknown command.\n"); + handle_help(0, NULL); + return; + } + + handlers[match](argc, argv); +} + +void cli_run() +{ + int c = getchar_timeout_us(0); + if (c == EOF) { + return; + } + + if (c == '\b' || c == 127) { // both backspace and delete + if (cmd_len > 0) { + cmd_len--; + printf("\b \b"); + } + return; + } + + if ((c != '\n') && (c != '\r')) { + + if (cmd_len < sizeof(cmd_buf) - 2) { + cmd_buf[cmd_len] = c; + printf("%c", c); + cmd_len++; + } + return; + } + + cmd_buf[cmd_len] = '\0'; + cmd_len = 0; + + printf("\n"); + + process_cmd(); + + printf(cli_prompt); +} + +void cli_init(const char *prompt, const char *logo) +{ + if (prompt) { + cli_prompt = prompt; + } + if (logo) { + cli_logo = logo; + } + + cli_register("?", handle_help, "Display this help message."); + cli_register("fps", handle_fps, "Display FPS."); + cli_register("update", handle_update, "Update firmware."); +}