281 lines
7.8 KiB
C
281 lines
7.8 KiB
C
/**
|
|
******************************************************************************
|
|
* @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 <stdint.h>
|
|
#include <ctype.h>
|
|
#include <stdio.h>
|
|
#include <string.h> //strchr
|
|
#include <stdlib.h> //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;
|
|
}
|