mirror of
https://github.com/iNavFlight/inav.git
synced 2025-07-23 08:15:26 +03:00
Merge pull request #3548 from iNavFlight/agh_settings_info
Add support for retriving setting types and listing all of them
This commit is contained in:
commit
6b6b49451b
8 changed files with 202 additions and 34 deletions
|
@ -428,7 +428,7 @@ static int cmsDrawMenuEntry(displayPort_t *pDisplay, const OSD_Entry *p, uint8_t
|
|||
if (IS_PRINTVALUE(p, screenRow) && p->data) {
|
||||
buff[0] = '\0';
|
||||
const OSD_SETTING_t *ptr = p->data;
|
||||
const setting_t *var = &settingsTable[ptr->val];
|
||||
const setting_t *var = settingGet(ptr->val);
|
||||
int32_t value;
|
||||
const void *valuePointer = settingGetValuePointer(var);
|
||||
switch (SETTING_TYPE(var)) {
|
||||
|
@ -476,13 +476,7 @@ static int cmsDrawMenuEntry(displayPort_t *pDisplay, const OSD_Entry *p, uint8_t
|
|||
break;
|
||||
case MODE_LOOKUP:
|
||||
{
|
||||
const char *str = NULL;
|
||||
if (var->config.lookup.tableIndex < LOOKUP_TABLE_COUNT) {
|
||||
const lookupTableEntry_t *tableEntry = &settingLookupTables[var->config.lookup.tableIndex];
|
||||
if (value < tableEntry->valueCount) {
|
||||
str = tableEntry->values[value];
|
||||
}
|
||||
}
|
||||
const char *str = settingLookupValueName(var, value);
|
||||
strncpy(buff, str ? str : "INVALID", sizeof(buff) - 1);
|
||||
}
|
||||
break;
|
||||
|
@ -1008,7 +1002,7 @@ STATIC_UNIT_TESTED uint16_t cmsHandleKey(displayPort_t *pDisplay, uint8_t key)
|
|||
case OME_Setting:
|
||||
if (p->data) {
|
||||
const OSD_SETTING_t *ptr = p->data;
|
||||
const setting_t *var = &settingsTable[ptr->val];
|
||||
const setting_t *var = settingGet(ptr->val);
|
||||
setting_min_t min = settingGetMin(var);
|
||||
setting_max_t max = settingGetMax(var);
|
||||
float step = ptr->step ?: 1;
|
||||
|
|
|
@ -113,3 +113,7 @@
|
|||
#define PG_RESERVED_FOR_TESTING_2 4094
|
||||
#define PG_RESERVED_FOR_TESTING_3 4093
|
||||
|
||||
#define PG_ID_INVALID 0
|
||||
#define PG_ID_FIRST PG_CF_START
|
||||
#define PG_ID_LAST PG_INAV_END
|
||||
|
||||
|
|
|
@ -352,14 +352,17 @@ static void printValuePointer(const setting_t *var, const void *valuePointer, ui
|
|||
}
|
||||
break;
|
||||
case MODE_LOOKUP:
|
||||
if (var->config.lookup.tableIndex < LOOKUP_TABLE_COUNT) {
|
||||
cliPrintf(settingLookupTables[var->config.lookup.tableIndex].values[value]);
|
||||
{
|
||||
const char *name = settingLookupValueName(var, value);
|
||||
if (name) {
|
||||
cliPrintf(name);
|
||||
} else {
|
||||
settingGetName(var, buf);
|
||||
cliPrintLinef("VALUE %s OUT OF RANGE", buf);
|
||||
cliPrintLinef("VALUE %d OUT OF RANGE FOR %s", (int)value, buf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool valuePtrEqualsDefault(const setting_t *value, const void *ptr, const void *ptrDefault)
|
||||
|
@ -425,8 +428,8 @@ static void dumpPgValue(const setting_t *value, uint8_t dumpMask)
|
|||
|
||||
static void dumpAllValues(uint16_t valueSection, uint8_t dumpMask)
|
||||
{
|
||||
for (uint32_t i = 0; i < SETTINGS_TABLE_COUNT; i++) {
|
||||
const setting_t *value = &settingsTable[i];
|
||||
for (unsigned i = 0; i < SETTINGS_TABLE_COUNT; i++) {
|
||||
const setting_t *value = settingGet(i);
|
||||
bufWriterFlush(cliWriter);
|
||||
if (SETTING_SECTION(value) == valueSection) {
|
||||
dumpPgValue(value, dumpMask);
|
||||
|
@ -453,7 +456,7 @@ static void cliPrintVarRange(const setting_t *var)
|
|||
break;
|
||||
case MODE_LOOKUP:
|
||||
{
|
||||
const lookupTableEntry_t *tableEntry = &settingLookupTables[var->config.lookup.tableIndex];
|
||||
const lookupTableEntry_t *tableEntry = settingLookupTable(var);
|
||||
cliPrint("Allowed values:");
|
||||
for (uint32_t i = 0; i < tableEntry->valueCount ; i++) {
|
||||
if (i > 0)
|
||||
|
@ -2256,7 +2259,7 @@ static void cliGet(char *cmdline)
|
|||
char name[SETTING_MAX_NAME_LENGTH];
|
||||
|
||||
for (uint32_t i = 0; i < SETTINGS_TABLE_COUNT; i++) {
|
||||
val = &settingsTable[i];
|
||||
val = settingGet(i);
|
||||
if (settingNameContains(val, name, cmdline)) {
|
||||
cliPrintf("%s = ", name);
|
||||
cliPrintVar(val, 0);
|
||||
|
@ -2288,7 +2291,7 @@ static void cliSet(char *cmdline)
|
|||
if (len == 0 || (len == 1 && cmdline[0] == '*')) {
|
||||
cliPrintLine("Current settings:");
|
||||
for (uint32_t i = 0; i < SETTINGS_TABLE_COUNT; i++) {
|
||||
val = &settingsTable[i];
|
||||
val = settingGet(i);
|
||||
settingGetName(val, name);
|
||||
cliPrintf("%s = ", name);
|
||||
cliPrintVar(val, len); // when len is 1 (when * is passed as argument), it will print min/max values as well, for gui
|
||||
|
@ -2310,7 +2313,7 @@ static void cliSet(char *cmdline)
|
|||
}
|
||||
|
||||
for (uint32_t i = 0; i < SETTINGS_TABLE_COUNT; i++) {
|
||||
val = &settingsTable[i];
|
||||
val = settingGet(i);
|
||||
// ensure exact match when setting to prevent setting variables with shorter names
|
||||
if (settingNameIsExactMatch(val, name, cmdline, variableNameLength)) {
|
||||
const setting_type_e type = SETTING_TYPE(val);
|
||||
|
@ -2341,7 +2344,7 @@ static void cliSet(char *cmdline)
|
|||
}
|
||||
break;
|
||||
case MODE_LOOKUP: {
|
||||
const lookupTableEntry_t *tableEntry = &settingLookupTables[settingsTable[i].config.lookup.tableIndex];
|
||||
const lookupTableEntry_t *tableEntry = settingLookupTable(val);
|
||||
bool matched = false;
|
||||
for (uint32_t tableValueIndex = 0; tableValueIndex < tableEntry->valueCount && !matched; tableValueIndex++) {
|
||||
matched = sl_strcasecmp(tableEntry->values[tableValueIndex], eqptr) == 0;
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
#include "common/time.h"
|
||||
#include "common/utils.h"
|
||||
|
||||
#include "config/parameter_group_ids.h"
|
||||
|
||||
#include "drivers/accgyro/accgyro.h"
|
||||
#include "drivers/bus_i2c.h"
|
||||
#include "drivers/compass/compass.h"
|
||||
|
@ -2549,9 +2551,10 @@ static mspResult_e mspFcProcessInCommand(uint16_t cmdMSP, sbuf_t *src)
|
|||
return MSP_RESULT_ACK;
|
||||
}
|
||||
|
||||
static const setting_t *mspReadSettingName(sbuf_t *src)
|
||||
static const setting_t *mspReadSetting(sbuf_t *src)
|
||||
{
|
||||
char name[SETTING_MAX_NAME_LENGTH];
|
||||
uint16_t id;
|
||||
uint8_t c;
|
||||
size_t s = 0;
|
||||
while (1) {
|
||||
|
@ -2560,6 +2563,14 @@ static const setting_t *mspReadSettingName(sbuf_t *src)
|
|||
}
|
||||
name[s++] = c;
|
||||
if (c == '\0') {
|
||||
if (s == 1) {
|
||||
// Payload starts with a zero, setting index
|
||||
// as uint16_t follows
|
||||
if (sbufReadU16Safe(&id, src)) {
|
||||
return settingGet(id);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (s == SETTING_MAX_NAME_LENGTH) {
|
||||
|
@ -2572,7 +2583,7 @@ static const setting_t *mspReadSettingName(sbuf_t *src)
|
|||
|
||||
static bool mspSettingCommand(sbuf_t *dst, sbuf_t *src)
|
||||
{
|
||||
const setting_t *setting = mspReadSettingName(src);
|
||||
const setting_t *setting = mspReadSetting(src);
|
||||
if (!setting) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2587,7 +2598,7 @@ static bool mspSetSettingCommand(sbuf_t *dst, sbuf_t *src)
|
|||
{
|
||||
UNUSED(dst);
|
||||
|
||||
const setting_t *setting = mspReadSettingName(src);
|
||||
const setting_t *setting = mspReadSetting(src);
|
||||
if (!setting) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2679,6 +2690,94 @@ static bool mspSetSettingCommand(sbuf_t *dst, sbuf_t *src)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool mspSettingInfoCommand(sbuf_t *dst, sbuf_t *src)
|
||||
{
|
||||
const setting_t *setting = mspReadSetting(src);
|
||||
if (!setting) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parameter Group ID
|
||||
sbufWriteU16(dst, settingGetPgn(setting));
|
||||
|
||||
// Type, section and mode
|
||||
sbufWriteU8(dst, SETTING_TYPE(setting));
|
||||
sbufWriteU8(dst, SETTING_SECTION(setting));
|
||||
sbufWriteU8(dst, SETTING_MODE(setting));
|
||||
|
||||
// Min as int32_t
|
||||
int32_t min = settingGetMin(setting);
|
||||
sbufWriteU32(dst, (uint32_t)min);
|
||||
// Max as uint32_t
|
||||
uint32_t max = settingGetMax(setting);
|
||||
sbufWriteU32(dst, max);
|
||||
|
||||
// Absolute setting index
|
||||
sbufWriteU16(dst, settingGetIndex(setting));
|
||||
|
||||
// If the setting is profile based, send the current one
|
||||
// and the count, both as uint8_t. For MASTER_VALUE, we
|
||||
// send two zeroes, so the MSP client can assume there
|
||||
// will always be two bytes.
|
||||
switch (SETTING_SECTION(setting)) {
|
||||
case MASTER_VALUE:
|
||||
sbufWriteU8(dst, 0);
|
||||
sbufWriteU8(dst, 0);
|
||||
break;
|
||||
case PROFILE_VALUE:
|
||||
FALLTHROUGH;
|
||||
case CONTROL_RATE_VALUE:
|
||||
sbufWriteU8(dst, getConfigProfile());
|
||||
sbufWriteU8(dst, MAX_PROFILE_COUNT);
|
||||
break;
|
||||
case BATTERY_CONFIG_VALUE:
|
||||
sbufWriteU8(dst, getConfigBatteryProfile());
|
||||
sbufWriteU8(dst, MAX_BATTERY_PROFILE_COUNT);
|
||||
break;
|
||||
}
|
||||
|
||||
// If the setting uses a table, send each possible string (null terminated)
|
||||
if (SETTING_MODE(setting) == MODE_LOOKUP) {
|
||||
for (int ii = (int)min; ii <= (int)max; ii++) {
|
||||
const char *name = settingLookupValueName(setting, ii);
|
||||
sbufWriteDataSafe(dst, name, strlen(name) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, include the setting value. This way resource constrained callers
|
||||
// (e.g. a script in the radio) don't need to perform another call to retrieve
|
||||
// the value.
|
||||
const void *ptr = settingGetValuePointer(setting);
|
||||
size_t size = settingGetValueSize(setting);
|
||||
sbufWriteDataSafe(dst, ptr, size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool mspParameterGroupsCommand(sbuf_t *dst, sbuf_t *src)
|
||||
{
|
||||
uint16_t first;
|
||||
uint16_t last;
|
||||
uint16_t start;
|
||||
uint16_t end;
|
||||
|
||||
if (sbufReadU16Safe(&first, src)) {
|
||||
last = first;
|
||||
} else {
|
||||
first = PG_ID_FIRST;
|
||||
last = PG_ID_LAST;
|
||||
}
|
||||
|
||||
for (int ii = first; ii <= last; ii++) {
|
||||
if (settingsGetParameterGroupIndexes(ii, &start, &end)) {
|
||||
sbufWriteU16(dst, ii);
|
||||
sbufWriteU16(dst, start);
|
||||
sbufWriteU16(dst, end);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool mspFCProcessInOutCommand(uint16_t cmdMSP, sbuf_t *dst, sbuf_t *src, mspResult_e *ret)
|
||||
{
|
||||
switch (cmdMSP) {
|
||||
|
@ -2705,6 +2804,14 @@ bool mspFCProcessInOutCommand(uint16_t cmdMSP, sbuf_t *dst, sbuf_t *src, mspResu
|
|||
*ret = mspSetSettingCommand(dst, src) ? MSP_RESULT_ACK : MSP_RESULT_ERROR;
|
||||
break;
|
||||
|
||||
case MSP2_COMMON_SETTING_INFO:
|
||||
*ret = mspSettingInfoCommand(dst, src) ? MSP_RESULT_ACK : MSP_RESULT_ERROR;
|
||||
break;
|
||||
|
||||
case MSP2_COMMON_PG_LIST:
|
||||
*ret = mspParameterGroupsCommand(dst, src) ? MSP_RESULT_ACK : MSP_RESULT_ERROR;
|
||||
break;
|
||||
|
||||
#if defined(USE_OSD)
|
||||
case MSP2_INAV_OSD_LAYOUTS:
|
||||
if (sbufBytesRemaining(src) >= 1) {
|
||||
|
|
|
@ -77,6 +77,16 @@ const setting_t *settingFind(const char *name)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
const setting_t *settingGet(unsigned index)
|
||||
{
|
||||
return index < SETTINGS_TABLE_COUNT ? &settingsTable[index] : NULL;
|
||||
}
|
||||
|
||||
unsigned settingGetIndex(const setting_t *val)
|
||||
{
|
||||
return val - settingsTable;
|
||||
}
|
||||
|
||||
size_t settingGetValueSize(const setting_t *val)
|
||||
{
|
||||
switch (SETTING_TYPE(val)) {
|
||||
|
@ -154,6 +164,23 @@ setting_max_t settingGetMax(const setting_t *val)
|
|||
return settingMinMaxTable[SETTING_INDEXES_GET_MAX(val)];
|
||||
}
|
||||
|
||||
const lookupTableEntry_t * settingLookupTable(const setting_t *val)
|
||||
{
|
||||
if (SETTING_MODE(val) == MODE_LOOKUP && val->config.lookup.tableIndex < LOOKUP_TABLE_COUNT) {
|
||||
return &settingLookupTables[val->config.lookup.tableIndex];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char * settingLookupValueName(const setting_t *val, unsigned v)
|
||||
{
|
||||
const lookupTableEntry_t *table = settingLookupTable(val);
|
||||
if (table && v < table->valueCount) {
|
||||
return table->values[v];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char * settingGetString(const setting_t *val)
|
||||
{
|
||||
if (SETTING_TYPE(val) == VAR_STRING) {
|
||||
|
@ -180,3 +207,21 @@ setting_max_t settingGetStringMaxLength(const setting_t *val)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool settingsGetParameterGroupIndexes(pgn_t pg, uint16_t *start, uint16_t *end)
|
||||
{
|
||||
unsigned acc = 0;
|
||||
for (int ii = 0; ii < SETTINGS_PGN_COUNT; ii++) {
|
||||
if (settingsPgn[ii] == pg) {
|
||||
if (start) {
|
||||
*start = acc;
|
||||
}
|
||||
if (end) {
|
||||
*end = acc + settingsPgnCounts[ii] - 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
acc += settingsPgnCounts[ii];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -13,8 +13,6 @@ typedef struct lookupTableEntry_s {
|
|||
const uint8_t valueCount;
|
||||
} lookupTableEntry_t;
|
||||
|
||||
extern const lookupTableEntry_t settingLookupTables[];
|
||||
|
||||
#define SETTING_TYPE_OFFSET 0
|
||||
#define SETTING_SECTION_OFFSET 4
|
||||
#define SETTING_MODE_OFFSET 6
|
||||
|
@ -69,8 +67,6 @@ typedef struct {
|
|||
|
||||
} __attribute__((packed)) setting_t;
|
||||
|
||||
extern const setting_t settingsTable[];
|
||||
|
||||
static inline setting_type_e SETTING_TYPE(const setting_t *s) { return s->type & SETTING_TYPE_MASK; }
|
||||
static inline setting_section_e SETTING_SECTION(const setting_t *s) { return s->type & SETTING_SECTION_MASK; }
|
||||
static inline setting_mode_e SETTING_MODE(const setting_t *s) { return s->type & SETTING_MODE_MASK; }
|
||||
|
@ -81,6 +77,11 @@ bool settingNameIsExactMatch(const setting_t *val, char *buf, const char *cmdlin
|
|||
// Returns a setting_t with the exact name (case sensitive), or
|
||||
// NULL if no setting with that name exists.
|
||||
const setting_t *settingFind(const char *name);
|
||||
// Returns the setting at the given index, or NULL if
|
||||
// the index is greater than the total count.
|
||||
const setting_t *settingGet(unsigned index);
|
||||
// Returns the setting index for the given setting.
|
||||
unsigned settingGetIndex(const setting_t *val);
|
||||
// Returns the size in bytes of the setting value.
|
||||
size_t settingGetValueSize(const setting_t *val);
|
||||
pgn_t settingGetPgn(const setting_t *val);
|
||||
|
@ -100,6 +101,13 @@ setting_min_t settingGetMin(const setting_t *val);
|
|||
// depends on the target and build options, but will always be an unsigned
|
||||
// integer (e.g. uintxx_t,)
|
||||
setting_max_t settingGetMax(const setting_t *val);
|
||||
// Returns the lookup table for the given setting. If the setting mode
|
||||
// is not MODE_LOOKUP, it returns NULL;
|
||||
const lookupTableEntry_t * settingLookupTable(const setting_t *val);
|
||||
// Returns the string in the table which corresponds to the value v
|
||||
// for the given setting. If the setting mode is not MODE_LOOKUP or
|
||||
// if the value is out of range, it returns NULL.
|
||||
const char * settingLookupValueName(const setting_t *val, unsigned v);
|
||||
// Returns the setting value as a const char * iff the setting is of type
|
||||
// VAR_STRING. Otherwise it returns NULL.
|
||||
const char * settingGetString(const setting_t *val);
|
||||
|
@ -109,4 +117,8 @@ const char * settingGetString(const setting_t *val);
|
|||
void settingSetString(const setting_t *val, const char *s, size_t size);
|
||||
// Returns the max string length (without counting the '\0' terminator)
|
||||
// for setting of type VAR_STRING. Otherwise it returns 0.
|
||||
setting_max_t settingGetStringMaxLength(const setting_t *val);
|
||||
setting_max_t settingGetStringMaxLength(const setting_t *val);
|
||||
|
||||
// Retrieve the setting indexes for the given PG. If the PG is not
|
||||
// found, these function returns false.
|
||||
bool settingsGetParameterGroupIndexes(pgn_t pg, uint16_t *start, uint16_t *end);
|
|
@ -15,10 +15,13 @@
|
|||
* along with INAV. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define MSP2_COMMON_TZ 0x1001 //out message Gets the TZ offset for the local time (returns: minutes(i16))
|
||||
#define MSP2_COMMON_SET_TZ 0x1002 //in message Sets the TZ offset for the local time (args: minutes(i16))
|
||||
#define MSP2_COMMON_SETTING 0x1003 //in/out message Returns the value for a setting
|
||||
#define MSP2_COMMON_SET_SETTING 0x1004 //in message Sets the value for a setting
|
||||
#define MSP2_COMMON_TZ 0x1001 //out message Gets the TZ offset for the local time (returns: minutes(i16))
|
||||
#define MSP2_COMMON_SET_TZ 0x1002 //in message Sets the TZ offset for the local time (args: minutes(i16))
|
||||
#define MSP2_COMMON_SETTING 0x1003 //in/out message Returns the value for a setting
|
||||
#define MSP2_COMMON_SET_SETTING 0x1004 //in message Sets the value for a setting
|
||||
|
||||
#define MSP2_COMMON_MOTOR_MIXER 0x1005
|
||||
#define MSP2_COMMON_SET_MOTOR_MIXER 0x1006
|
||||
|
||||
#define MSP2_COMMON_SETTING_INFO 0x1007 //in/out message Returns info about a setting (PG, type, flags, min/max, etc..).
|
||||
#define MSP2_COMMON_PG_LIST 0x1008 //in/out message Returns a list of the PG ids used by the settings
|
|
@ -468,7 +468,7 @@ class Generator
|
|||
buf << "};\n"
|
||||
end
|
||||
|
||||
buf << "const lookupTableEntry_t settingLookupTables[] = {\n"
|
||||
buf << "static const lookupTableEntry_t settingLookupTables[] = {\n"
|
||||
table_names.each do |name|
|
||||
vn = table_variable_name(name)
|
||||
buf << "\t{ #{vn}, sizeof(#{vn}) / sizeof(char*) },\n"
|
||||
|
@ -476,7 +476,7 @@ class Generator
|
|||
buf << "};\n"
|
||||
|
||||
# Write min/max values table
|
||||
buf << "const uint32_t settingMinMaxTable[] = {\n"
|
||||
buf << "static const uint32_t settingMinMaxTable[] = {\n"
|
||||
@value_encoder.values.each do |v|
|
||||
buf << "\t#{v},\n"
|
||||
end
|
||||
|
@ -492,7 +492,7 @@ class Generator
|
|||
end
|
||||
|
||||
# Write setting_t values
|
||||
buf << "const setting_t settingsTable[] = {\n"
|
||||
buf << "static const setting_t settingsTable[] = {\n"
|
||||
|
||||
last_group = nil
|
||||
foreach_enabled_member do |group, member|
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue