diff --git a/src/main/interface/cli.c b/src/main/interface/cli.c index 297406079e..45d4cd03af 100644 --- a/src/main/interface/cli.c +++ b/src/main/interface/cli.c @@ -371,6 +371,9 @@ static void printValuePointer(const clivalue_t *var, const void *valuePointer, b case VAR_INT16: value = *(int16_t *)valuePointer; break; + case VAR_UINT32: + value = *(uint32_t *)valuePointer; + break; } switch (var->type & VALUE_MODE_MASK) { @@ -383,6 +386,12 @@ static void printValuePointer(const clivalue_t *var, const void *valuePointer, b case MODE_LOOKUP: cliPrint(lookupTables[var->config.lookup.tableIndex].values[value]); break; + case MODE_BITSET: + if (value & 1 << var->config.bitpos) { + cliPrintf("ON"); + } else { + cliPrintf("OFF"); + } } } } @@ -392,14 +401,18 @@ static bool valuePtrEqualsDefault(const clivalue_t *var, const void *ptr, const { bool result = true; int elementCount = 1; + uint32_t mask = 0xffffffff; if ((var->type & VALUE_MODE_MASK) == MODE_ARRAY) { elementCount = var->config.array.length; } + if ((var->type & VALUE_MODE_MASK) == MODE_BITSET) { + mask = 1 << var->config.bitpos; + } for (int i = 0; i < elementCount; i++) { switch (var->type & VALUE_TYPE_MASK) { case VAR_UINT8: - result = result && ((uint8_t *)ptr)[i] == ((uint8_t *)ptrDefault)[i]; + result = result && (((uint8_t *)ptr)[i] & mask) == (((uint8_t *)ptrDefault)[i] & mask); break; case VAR_INT8: @@ -407,9 +420,14 @@ static bool valuePtrEqualsDefault(const clivalue_t *var, const void *ptr, const break; case VAR_UINT16: + result = result && (((int16_t *)ptr)[i] & mask) == (((int16_t *)ptrDefault)[i] & mask); + break; case VAR_INT16: result = result && ((int16_t *)ptr)[i] == ((int16_t *)ptrDefault)[i]; break; + case VAR_UINT32: + result = result && (((uint32_t *)ptr)[i] & mask) == (((uint32_t *)ptrDefault)[i] & mask); + break; } } @@ -512,7 +530,10 @@ static void cliPrintVarRange(const clivalue_t *var) case (MODE_ARRAY): { cliPrintLinef("Array length: %d", var->config.array.length); } - + break; + case (MODE_BITSET): { + cliPrintLinef("Allowed values: OFF, ON"); + } break; } } @@ -520,20 +541,57 @@ static void cliPrintVarRange(const clivalue_t *var) static void cliSetVar(const clivalue_t *var, const int16_t value) { void *ptr = cliGetValuePointer(var); + uint32_t workValue; + uint32_t mask; - switch (var->type & VALUE_TYPE_MASK) { - case VAR_UINT8: - *(uint8_t *)ptr = value; - break; + if ((var->type & VALUE_MODE_MASK) == MODE_BITSET) { + switch (var->type & VALUE_TYPE_MASK) { + case VAR_UINT8: + mask = (1 << var->config.bitpos) & 0xff; + if (value) { + workValue = *(uint8_t *)ptr | mask; + } else { + workValue = *(uint8_t *)ptr & ~mask; + } + *(uint8_t *)ptr = workValue; + break; - case VAR_INT8: - *(int8_t *)ptr = value; - break; + case VAR_UINT16: + mask = (1 << var->config.bitpos) & 0xffff; + if (value) { + workValue = *(uint16_t *)ptr | mask; + } else { + workValue = *(uint16_t *)ptr & ~mask; + } + *(uint16_t *)ptr = workValue; + break; - case VAR_UINT16: - case VAR_INT16: - *(int16_t *)ptr = value; - break; + case VAR_UINT32: + mask = 1 << var->config.bitpos; + if (value) { + workValue = *(uint32_t *)ptr | mask; + } else { + workValue = *(uint32_t *)ptr & ~mask; + } + *(uint32_t *)ptr = workValue; + break; + + } + } else { + switch (var->type & VALUE_TYPE_MASK) { + case VAR_UINT8: + *(uint8_t *)ptr = value; + break; + + case VAR_INT8: + *(int8_t *)ptr = value; + break; + + case VAR_UINT16: + case VAR_INT16: + *(int16_t *)ptr = value; + break; + } } } @@ -3032,8 +3090,15 @@ STATIC_UNIT_TESTED void cliSet(char *cmdline) } break; - case MODE_LOOKUP: { - const lookupTableEntry_t *tableEntry = &lookupTables[val->config.lookup.tableIndex]; + case MODE_LOOKUP: + case MODE_BITSET: { + int tableIndex; + if ((val->type & VALUE_MODE_MASK) == MODE_BITSET) { + tableIndex = TABLE_OFF_ON; + } else { + tableIndex = val->config.lookup.tableIndex; + } + const lookupTableEntry_t *tableEntry = &lookupTables[tableIndex]; bool matched = false; for (uint32_t tableValueIndex = 0; tableValueIndex < tableEntry->valueCount && !matched; tableValueIndex++) { matched = tableEntry->values[tableValueIndex] && strcasecmp(tableEntry->values[tableValueIndex], eqptr) == 0; @@ -3048,6 +3113,7 @@ STATIC_UNIT_TESTED void cliSet(char *cmdline) } break; + case MODE_ARRAY: { const uint8_t arrayLength = val->config.array.length; char *valPtr = eqptr; @@ -3111,6 +3177,7 @@ STATIC_UNIT_TESTED void cliSet(char *cmdline) valueChanged = true; break; + } if (valueChanged) { diff --git a/src/main/interface/settings.h b/src/main/interface/settings.h index 0d0bc0209a..a536845e6f 100644 --- a/src/main/interface/settings.h +++ b/src/main/interface/settings.h @@ -104,31 +104,33 @@ typedef struct lookupTableEntry_s { #define VALUE_TYPE_OFFSET 0 -#define VALUE_SECTION_OFFSET 2 -#define VALUE_MODE_OFFSET 4 +#define VALUE_SECTION_OFFSET 3 +#define VALUE_MODE_OFFSET 5 typedef enum { - // value type, bits 0-1 + // value type, bits 0-2 VAR_UINT8 = (0 << VALUE_TYPE_OFFSET), VAR_INT8 = (1 << VALUE_TYPE_OFFSET), VAR_UINT16 = (2 << VALUE_TYPE_OFFSET), VAR_INT16 = (3 << VALUE_TYPE_OFFSET), + VAR_UINT32 = (4 << VALUE_TYPE_OFFSET), - // value section, bits 2-3 + // value section, bits 3-4 MASTER_VALUE = (0 << VALUE_SECTION_OFFSET), PROFILE_VALUE = (1 << VALUE_SECTION_OFFSET), PROFILE_RATE_VALUE = (2 << VALUE_SECTION_OFFSET), - // value mode, bits 4-5 + // value mode, bits 5-6 MODE_DIRECT = (0 << VALUE_MODE_OFFSET), MODE_LOOKUP = (1 << VALUE_MODE_OFFSET), - MODE_ARRAY = (2 << VALUE_MODE_OFFSET) + MODE_ARRAY = (2 << VALUE_MODE_OFFSET), + MODE_BITSET = (3 << VALUE_MODE_OFFSET) } cliValueFlag_e; -#define VALUE_TYPE_MASK (0x03) -#define VALUE_SECTION_MASK (0x0c) -#define VALUE_MODE_MASK (0x30) +#define VALUE_TYPE_MASK (0x07) +#define VALUE_SECTION_MASK (0x18) +#define VALUE_MODE_MASK (0x60) typedef struct cliMinMaxConfig_s { const int16_t min; @@ -147,6 +149,7 @@ typedef union { cliLookupTableConfig_t lookup; cliMinMaxConfig_t minmax; cliArrayLengthConfig_t array; + uint8_t bitpos; } cliValueConfig_t; typedef struct clivalue_s {