/** ****************************************************************************** * @file commands.c * @brief command.c file, the command interpreter, a generic one ****************************************************************************** * @author: Thomas Kuschel KW4NZ * created 2022-06-04 * ******************************************************************************/ #include "main.h" #include "at1_defines.h" #include "cmsis_os.h" #include #include #include #include //strchr #include //bsearch #include "helper.h" //ltrim #include "si5351.h" #include "commands.h" /* typedef struct command_ctx_s { osThreadId_t thread_id; osMutexId_t mutex; char *last_cmd; size_t last_cmd_size; } command_ctx_t; */ typedef enum { CMD_NO_FLAG = 0x00, CMD_HIDDEN = 0x01, /*!< Not shown in help but listed with "help all" or with "?" */ CMD_SECRET = 0x02, /*!< Not shown in help - hidden and secret commands */ CMD_ADMIN = 0x04, /*!< Only an administrator or privileged person can use this command */ CMD_NOT_IMPLEMENTED = 0x80 /*!< A command which is not implemented yet */ } cmd_flags_t; #define CMD_LENGTH 16 #define MAXLINELENGTH 40 typedef struct { const char name[CMD_LENGTH]; /*!< command name */ const uint8_t significantlength; /*!< length of command for the compare function */ const uint8_t flag; /*!< command flags, i.e. CMD_HIDDEN, CMD_SECRET, CMD_ADMIN, etc. */ int (*func)(/*command_ctx_t *ctx,*/ char *args); } cmd_table_t; // the entries must be in alphabetical order due to the binary search static const cmd_table_t cmd_table[] = { {"admin", 2, CMD_ADMIN, do_test }, {"altitude", 1, CMD_NO_FLAG, do_test }, {"date", 1, CMD_NO_FLAG, do_time }, {"devid", 3, CMD_HIDDEN, do_devid }, {"frequency",1, CMD_NO_FLAG, do_frequ }, {"help", 1, CMD_NO_FLAG, do_help }, {"hidden", 2, CMD_HIDDEN, do_test }, {"info", 1, CMD_NO_FLAG, do_info }, {"sinfo", 1, CMD_SECRET, do_sinfo }, {"time", 1, CMD_NO_FLAG, do_time }, }; int do_test(char *args) { (void) *args; printf("not implemented.\n"); return 0; } /*! * @brief compares two strings up to n characters, and next gets the pointer to the 2nd word in the string s1 * * @pre s1, s2 and n not allowed to be 0 * * @param s1 * @param next * @param s2 * @param n * @return int if the s1 and s2 are the same till n characters its 0, if s1 > s2 it becomes 1, else -1 */ int cmdncasecmp(const char *s1, char **next, const char *s2, size_t n) { if (n == 0 || s1 == NULL || s2 == NULL) { if (next) *next = NULL; if (s2 == NULL && s1 != NULL) return 1; if (s1 == NULL && s2 != NULL) return -1; return 0; } int ret; while ((ret = ((unsigned char)tolower(*s1) - (unsigned char)tolower(*s2))) == 0 && *s1 != ' ' && *s1 && *s2) { if (n) n--; s1++; s2++; } if (next) *next = (char *) s1; if (n == 0 && (*s1 == ' ' || !*s1)) return 0; return ret; } static int compar(const void *a, const void *b) { cmd_table_t * cmd = (cmd_table_t *)b; return cmdncasecmp(a, NULL, cmd->name, cmd->significantlength); } int cmd_interpreter(char * cmdline) { char * ptr; const cmd_table_t *entry; int rv = 0; ptr = strchr(cmdline, ' '); if (ptr) { *ptr = '\0'; ptr++; ptr = ltrim(ptr); } entry = bsearch(cmdline, cmd_table, sizeof(cmd_table)/sizeof(cmd_table[0]), sizeof(cmd_table[0]), compar); if (entry == NULL) { printf("Command \"%s\" not found.\n", cmdline); } else { printf("Command \"%s\":\n", entry->name); if (*ptr != '\0') printf("called with parameter: \"%s\"\n", ptr); rv = entry->func(ptr); } return rv; } int do_devid(char *args) { (void)args; union myUnion { uint32_t myint[2]; char mychar[8]; } my; printf("DEVID: 0x%08lx\n", HAL_GetDEVID()); printf("REVID: 0x%08lx\n", HAL_GetREVID()); printf("UID: 0x %08lx %08lx %08lx\n", HAL_GetUIDw2(), HAL_GetUIDw1(), HAL_GetUIDw0()); my.myint[0] = HAL_GetUIDw1(); my.myint[1] = HAL_GetUIDw2(); printf("=> X: %2lx, Y: %2lx\n", HAL_GetUIDw0() >> 16, HAL_GetUIDw0() & 0xffff); printf("=> Lot Number: %.6s\n", my.mychar + 1); printf("=> Wafer Number: %u\n", (uint8_t)(HAL_GetUIDw1() & 0xff)); // printf("=> 1.Char: %x, 8.Char: %x\n", my.mychar[0], my.mychar[7]); return 0; } int do_frequ(char *args) { int rv; (void)args; si5351_inst_t inst = NULL; uint32_t frequency; uint32_t xtal_frequency; rv = si5351_get_instance(&inst); if (rv > 0) { if (rv == 1) { /* nothing */ } if (!args) { printf("Frequency: %lu Hz\n", si5351_get_frequency(inst)); } else { rv = strtouint32(args, &frequency); if (!rv) { synthesis_t syn; xtal_frequency = si5351_get_xtal(inst); syn = si5351_calculation(frequency, xtal_frequency); printf("out_r_divider: %u\n", syn.out_r_divider); printf("out_multiplier: %lu\n", syn.out_multiplier); printf("out_numerator: %lu\n", syn.out_numerator); printf("out_denumerator:%lu\n",syn.out_denominator); printf("pll_multiplier: %lu\n", syn.pll_multiplier); printf("pll_numerator: %lu\n", syn.pll_numerator); printf("pll_denominator:%lu\n", syn.pll_denominator); rv = si5351_set_frequency(inst, frequency); } } } return 0; } int do_info(char *args) { (void)args; print_system_info(); return 0; } int do_sinfo(char *args) { int rv = 0; (void)args; si5351_inst_t inst = NULL; rv = si5351_get_instance(&inst); printf("%d Si5351 instance%s found.\n", rv, (rv==1)?"":"s"); while (rv > 0) { printf("Si5351 Handle: 0x%08lx\n", (uint32_t)inst); printf(" I2C address: 0x%02x\n", si5351_get_i2c_address(inst)); rv = si5351_get_instance(&inst); } return rv; } int do_time(char *args) { HAL_StatusTypeDef status; RTC_TimeTypeDef stime = {0}; RTC_DateTypeDef sdate = {0}; int rv = 0; if (args) { struct _tm_ tp; rv = strtotime (args, &tp); if (rv > 0) { printf("%02d%02d-%02d-%02d %02d:%02d:%02d\n", (tp.year < DATE_COMPILE_YEAR) ? DATE_COMPILE_CENTURY + 1 : DATE_COMPILE_CENTURY, \ tp.year, tp.mon, tp.day, tp.hour, tp.min, tp.sec); /** Initialize RTC and set the Time and Date */ stime.Hours = (uint8_t)tp.hour; stime.Minutes = (uint8_t)tp.min; stime.Seconds = (uint8_t)tp.sec; stime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; stime.StoreOperation = RTC_STOREOPERATION_RESET; if (HAL_RTC_SetTime(&hrtc, &stime, RTC_FORMAT_BIN) != HAL_OK) { Error_Handler(); } sdate.WeekDay = RTC_WEEKDAY_MONDAY; sdate.Month = (uint8_t)tp.mon; sdate.Date = (uint8_t)tp.day; sdate.Year = (uint8_t)tp.year; //uint8_t weekday; //weekday = dayofweek((tp.year < DATE_COMPILE_YEAR) ? DATE_COMPILE_CENTURY + 1 : DATE_COMPILE_CENTURY, sdate.Year, sdate.Month, sdate.Date); //printf("Wochentag: %d\n", weekday); if (HAL_RTC_SetDate(&hrtc, &sdate, RTC_FORMAT_BIN) != HAL_OK) { Error_Handler(); } } } status = HAL_RTC_GetTime(&hrtc, &stime, RTC_FORMAT_BIN); if (status != HAL_OK) puts("HAL_RTC_GetTime problem..."); status = HAL_RTC_GetDate(&hrtc, &sdate, RTC_FORMAT_BIN); printf("%02d%02d-%02d-%02d %02d:%02d:%02d\n", (sdate.Year < DATE_COMPILE_YEAR) ? DATE_COMPILE_CENTURY + 1 : DATE_COMPILE_CENTURY, \ sdate.Year, sdate.Month, sdate.Date, stime.Hours, stime.Minutes, stime.Seconds); return rv; } int do_help(char *args) { int all = cmdncasecmp(args, NULL, "all", 1); const cmd_table_t *cmd = cmd_table; int j = 0; int n = 0; int rv = 0; puts("Commands:"); for (size_t i = 0; i < (sizeof(cmd_table)/sizeof(cmd_table[0])); i++, cmd++) { if (cmd->flag != CMD_SECRET && (cmd->flag != CMD_HIDDEN || !all)) { if (n >= MAXLINELENGTH) { puts(","); n = 0; } // n += printf("%s%s (%.*s)", n?", ":"", cmd->name, cmd->significantlength, cmd->name); n += printf("%s(%.*s)%s", n?", ":"", cmd->significantlength, cmd->name, cmd->name + cmd->significantlength); j++; } } printf("\n%d commands found.\n", j); return rv; }