Added support for array variables to CLI.

This commit is contained in:
Michael Keller 2017-06-16 23:02:07 +12:00 committed by mikeller
parent 1388c3ee82
commit a5b428ae4f
2 changed files with 145 additions and 81 deletions

View File

@ -293,33 +293,44 @@ static void cliPrintLinef(const char *format, ...)
static void printValuePointer(const clivalue_t *var, const void *valuePointer, bool full) static void printValuePointer(const clivalue_t *var, const void *valuePointer, bool full)
{ {
int value = 0; if ((var->type & VALUE_MODE_MASK) == MODE_ARRAY) {
for (int i = 0; i < var->config.array.length; i++) {
uint8_t value = ((uint8_t *)valuePointer)[i];
switch (var->type & VALUE_TYPE_MASK) { cliPrintf("%d", value);
case VAR_UINT8: if (i < var->config.array.length - 1) {
value = *(uint8_t *)valuePointer; cliPrint(", ");
break; }
}
case VAR_INT8: } else {
value = *(int8_t *)valuePointer; int value = 0;
break;
switch (var->type & VALUE_TYPE_MASK) {
case VAR_UINT16: case VAR_UINT8:
case VAR_INT16: value = *(uint8_t *)valuePointer;
value = *(int16_t *)valuePointer; break;
break;
} case VAR_INT8:
value = *(int8_t *)valuePointer;
switch(var->type & VALUE_MODE_MASK) { break;
case MODE_DIRECT:
cliPrintf("%d", value); case VAR_UINT16:
if (full) { case VAR_INT16:
cliPrintf(" %d %d", var->config.minmax.min, var->config.minmax.max); value = *(int16_t *)valuePointer;
break;
}
switch(var->type & VALUE_MODE_MASK) {
case MODE_DIRECT:
cliPrintf("%d", value);
if (full) {
cliPrintf(" %d %d", var->config.minmax.min, var->config.minmax.max);
}
break;
case MODE_LOOKUP:
cliPrint(lookupTables[var->config.lookup.tableIndex].values[value]);
break;
} }
break;
case MODE_LOOKUP:
cliPrint(lookupTables[var->config.lookup.tableIndex].values[value]);
break;
} }
} }
@ -377,14 +388,15 @@ static void dumpPgValue(const clivalue_t *value, uint8_t dumpMask)
const char *defaultFormat = "#set %s = "; const char *defaultFormat = "#set %s = ";
const int valueOffset = getValueOffset(value); const int valueOffset = getValueOffset(value);
const bool equalsDefault = valuePtrEqualsDefault(value->type, pg->copy + valueOffset, pg->address + valueOffset); const bool equalsDefault = valuePtrEqualsDefault(value->type, pg->copy + valueOffset, pg->address + valueOffset);
if (((dumpMask & DO_DIFF) == 0) || !equalsDefault) { if (((dumpMask & DO_DIFF) == 0) || !equalsDefault) {
if (dumpMask & SHOW_DEFAULTS && !equalsDefault) { if (dumpMask & SHOW_DEFAULTS && !equalsDefault) {
cliPrintf(defaultFormat, value->name); cliPrintf(defaultFormat, value->name);
printValuePointer(value, (uint8_t*)pg->address + valueOffset, 0); printValuePointer(value, (uint8_t*)pg->address + valueOffset, false);
cliPrintLinefeed(); cliPrintLinefeed();
} }
cliPrintf(format, value->name); cliPrintf(format, value->name);
printValuePointer(value, pg->copy + valueOffset, 0); printValuePointer(value, pg->copy + valueOffset, false);
cliPrintLinefeed(); cliPrintLinefeed();
} }
} }
@ -424,26 +436,31 @@ static void cliPrintVarRange(const clivalue_t *var)
} }
cliPrintLinefeed(); cliPrintLinefeed();
} }
break;
case (MODE_ARRAY): {
cliPrintLinef("Array length: %d", var->config.array.length);
}
break; break;
} }
} }
static void cliSetVar(const clivalue_t *var, const cliVar_t value) static void cliSetVar(const clivalue_t *var, const int16_t value)
{ {
void *ptr = getValuePointer(var); void *ptr = getValuePointer(var);
switch (var->type & VALUE_TYPE_MASK) { switch (var->type & VALUE_TYPE_MASK) {
case VAR_UINT8: case VAR_UINT8:
*(uint8_t *)ptr = value.uint8; *(uint8_t *)ptr = value;
break; break;
case VAR_INT8: case VAR_INT8:
*(int8_t *)ptr = value.int8; *(int8_t *)ptr = value;
break; break;
case VAR_UINT16: case VAR_UINT16:
case VAR_INT16: case VAR_INT16:
*(int16_t *)ptr = value.int16; *(int16_t *)ptr = value;
break; break;
} }
} }
@ -2507,18 +2524,34 @@ static void cliGet(char *cmdline)
cliPrintLine("Invalid name"); cliPrintLine("Invalid name");
} }
static char *skipSpace(char *buffer)
{
while (*(buffer) == ' ') {
buffer++;
}
return buffer;
}
static uint8_t getWordLength(char *bufBegin, char *bufEnd)
{
while (*(bufEnd - 1) == ' ') {
bufEnd--;
}
return bufEnd - bufBegin;
}
static void cliSet(char *cmdline) static void cliSet(char *cmdline)
{ {
uint32_t len; const uint32_t len = strlen(cmdline);
const clivalue_t *val; char *eqptr;
char *eqptr = NULL;
len = strlen(cmdline);
if (len == 0 || (len == 1 && cmdline[0] == '*')) { if (len == 0 || (len == 1 && cmdline[0] == '*')) {
cliPrintLine("Current settings: "); cliPrintLine("Current settings: ");
for (uint32_t i = 0; i < valueTableEntryCount; i++) { for (uint32_t i = 0; i < valueTableEntryCount; i++) {
val = &valueTable[i]; const clivalue_t *val = &valueTable[i];
cliPrintf("%s = ", valueTable[i].name); cliPrintf("%s = ", valueTable[i].name);
cliPrintVar(val, len); // when len is 1 (when * is passed as argument), it will print min/max values as well, for gui cliPrintVar(val, len); // when len is 1 (when * is passed as argument), it will print min/max values as well, for gui
cliPrintLinefeed(); cliPrintLinefeed();
@ -2526,52 +2559,81 @@ static void cliSet(char *cmdline)
} else if ((eqptr = strstr(cmdline, "=")) != NULL) { } else if ((eqptr = strstr(cmdline, "=")) != NULL) {
// has equals // has equals
char *lastNonSpaceCharacter = eqptr; uint8_t variableNameLength = getWordLength(cmdline, eqptr);
while (*(lastNonSpaceCharacter - 1) == ' ') {
lastNonSpaceCharacter--;
}
uint8_t variableNameLength = lastNonSpaceCharacter - cmdline;
// skip the '=' and any ' ' characters // skip the '=' and any ' ' characters
eqptr++; eqptr++;
while (*(eqptr) == ' ') { eqptr = skipSpace(eqptr);
eqptr++;
}
for (uint32_t i = 0; i < valueTableEntryCount; i++) { for (uint32_t i = 0; i < valueTableEntryCount; i++) {
val = &valueTable[i]; const clivalue_t *val = &valueTable[i];
// ensure exact match when setting to prevent setting variables with shorter names // ensure exact match when setting to prevent setting variables with shorter names
if (strncasecmp(cmdline, valueTable[i].name, strlen(valueTable[i].name)) == 0 && variableNameLength == strlen(valueTable[i].name)) { if (strncasecmp(cmdline, valueTable[i].name, strlen(valueTable[i].name)) == 0 && variableNameLength == strlen(valueTable[i].name)) {
bool changeValue = false; bool valueChanged = false;
cliVar_t value = { .int16 = 0 }; int16_t value = 0;
switch (valueTable[i].type & VALUE_MODE_MASK) { switch (valueTable[i].type & VALUE_MODE_MASK) {
case MODE_DIRECT: { case MODE_DIRECT: {
value.int16 = atoi(eqptr); int16_t value = atoi(eqptr);
if (value.int16 >= valueTable[i].config.minmax.min && value.int16 <= valueTable[i].config.minmax.max) { if (value >= valueTable[i].config.minmax.min && value <= valueTable[i].config.minmax.max) {
changeValue = true; cliSetVar(val, value);
} valueChanged = true;
} }
break; }
break;
case MODE_LOOKUP: { case MODE_LOOKUP: {
const lookupTableEntry_t *tableEntry = &lookupTables[valueTable[i].config.lookup.tableIndex]; const lookupTableEntry_t *tableEntry = &lookupTables[valueTable[i].config.lookup.tableIndex];
bool matched = false; bool matched = false;
for (uint32_t tableValueIndex = 0; tableValueIndex < tableEntry->valueCount && !matched; tableValueIndex++) { for (uint32_t tableValueIndex = 0; tableValueIndex < tableEntry->valueCount && !matched; tableValueIndex++) {
matched = strcasecmp(tableEntry->values[tableValueIndex], eqptr) == 0; matched = strcasecmp(tableEntry->values[tableValueIndex], eqptr) == 0;
if (matched) { if (matched) {
value.int16 = tableValueIndex; value = tableValueIndex;
changeValue = true;
} cliSetVar(val, value);
valueChanged = true;
} }
} }
break; }
break;
case MODE_ARRAY: {
const uint8_t arrayLength = valueTable[i].config.array.length;
char *valPtr = eqptr;
uint8_t array[256];
char curVal[4];
for (int i = 0; i < arrayLength; i++) {
valPtr = skipSpace(valPtr);
char *valEnd = strstr(valPtr, ",");
if ((valEnd != NULL) && (i < arrayLength - 1)) {
uint8_t varLength = getWordLength(valPtr, valEnd);
if (varLength <= 3) {
strncpy(curVal, valPtr, getWordLength(valPtr, valEnd));
curVal[varLength] = '\0';
array[i] = (uint8_t)atoi((const char *)curVal);
valPtr = valEnd + 1;
} else {
break;
}
} else if ((valEnd == NULL) && (i == arrayLength - 1)) {
array[i] = atoi(valPtr);
uint8_t *ptr = getValuePointer(val);
memcpy(ptr, array, arrayLength);
valueChanged = true;
} else {
break;
}
}
}
break;
} }
if (changeValue) { if (valueChanged) {
cliSetVar(val, value);
cliPrintf("%s set to ", valueTable[i].name); cliPrintf("%s set to ", valueTable[i].name);
cliPrintVar(val, 0); cliPrintVar(val, 0);
} else { } else {

View File

@ -69,34 +69,31 @@ typedef struct lookupTableEntry_s {
#define VALUE_TYPE_OFFSET 0 #define VALUE_TYPE_OFFSET 0
#define VALUE_SECTION_OFFSET 4 #define VALUE_SECTION_OFFSET 2
#define VALUE_MODE_OFFSET 6 #define VALUE_MODE_OFFSET 4
typedef enum { typedef enum {
// value type, bits 0-3 // value type, bits 0-1
VAR_UINT8 = (0 << VALUE_TYPE_OFFSET), VAR_UINT8 = (0 << VALUE_TYPE_OFFSET),
VAR_INT8 = (1 << VALUE_TYPE_OFFSET), VAR_INT8 = (1 << VALUE_TYPE_OFFSET),
VAR_UINT16 = (2 << VALUE_TYPE_OFFSET), VAR_UINT16 = (2 << VALUE_TYPE_OFFSET),
VAR_INT16 = (3 << VALUE_TYPE_OFFSET), VAR_INT16 = (3 << VALUE_TYPE_OFFSET),
// value section, bits 4-5 // value section, bits 2-3
MASTER_VALUE = (0 << VALUE_SECTION_OFFSET), MASTER_VALUE = (0 << VALUE_SECTION_OFFSET),
PROFILE_VALUE = (1 << VALUE_SECTION_OFFSET), PROFILE_VALUE = (1 << VALUE_SECTION_OFFSET),
PROFILE_RATE_VALUE = (2 << VALUE_SECTION_OFFSET), // 0x20 PROFILE_RATE_VALUE = (2 << VALUE_SECTION_OFFSET),
// value mode
MODE_DIRECT = (0 << VALUE_MODE_OFFSET), // 0x40 // value mode, bits 4-5
MODE_LOOKUP = (1 << VALUE_MODE_OFFSET) // 0x80 MODE_DIRECT = (0 << VALUE_MODE_OFFSET),
MODE_LOOKUP = (1 << VALUE_MODE_OFFSET),
MODE_ARRAY = (2 << VALUE_MODE_OFFSET)
} cliValueFlag_e; } cliValueFlag_e;
#define VALUE_TYPE_MASK (0x0F)
#define VALUE_SECTION_MASK (0x30)
#define VALUE_MODE_MASK (0xC0)
typedef union { #define VALUE_TYPE_MASK (0x03)
int8_t int8; #define VALUE_SECTION_MASK (0x0c)
uint8_t uint8; #define VALUE_MODE_MASK (0x30)
int16_t int16;
} cliVar_t;
typedef struct cliMinMaxConfig_s { typedef struct cliMinMaxConfig_s {
const int16_t min; const int16_t min;
@ -107,9 +104,14 @@ typedef struct cliLookupTableConfig_s {
const lookupTableIndex_e tableIndex; const lookupTableIndex_e tableIndex;
} cliLookupTableConfig_t; } cliLookupTableConfig_t;
typedef struct cliArrayLengthConfig_s {
const uint8_t length;
} cliArrayLengthConfig_t;
typedef union { typedef union {
cliLookupTableConfig_t lookup; cliLookupTableConfig_t lookup;
cliMinMaxConfig_t minmax; cliMinMaxConfig_t minmax;
cliArrayLengthConfig_t array;
} cliValueConfig_t; } cliValueConfig_t;
typedef struct { typedef struct {