From c0f3301da42f98088cead001ab2e80b44b32aec7 Mon Sep 17 00:00:00 2001 From: Oleg Kalachev Date: Thu, 22 Jan 2026 22:54:05 +0300 Subject: [PATCH] Support integer parameters in addition to floats The variable pointer is stored as a union field. If `.integer` field is true, then integer pointer should be used. Interfaces to parameters (cli and mavlink) keep working using floats. Setting a non-finite value to int parameter will cause an error. `.value` field is renamed to `.cache`. --- flix/mavlink.ino | 3 ++- flix/parameters.ino | 34 +++++++++++++++++++++------------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/flix/mavlink.ino b/flix/mavlink.ino index cb122fc..0366ca4 100644 --- a/flix/mavlink.ino +++ b/flix/mavlink.ino @@ -142,7 +142,8 @@ void handleMavlink(const void *_msg) { char name[MAVLINK_MSG_PARAM_SET_FIELD_PARAM_ID_LEN + 1]; strlcpy(name, m.param_id, sizeof(name)); // param_id might be not null-terminated - setParameter(name, m.param_value); + bool success = setParameter(name, m.param_value); + if (!success) return; // send ack mavlink_message_t msg; mavlink_msg_param_value_pack(SYSTEM_ID, MAV_COMP_ID_AUTOPILOT1, &msg, diff --git a/flix/parameters.ino b/flix/parameters.ino index 3d7bfdd..a6e7115 100644 --- a/flix/parameters.ino +++ b/flix/parameters.ino @@ -14,8 +14,13 @@ Preferences storage; struct Parameter { const char *name; // max length is 15 (Preferences key limit) - float *variable; - float value; // cache + bool integer; + union { float *f; int *i; }; // pointer to variable + float cache; // what's stored in flash + Parameter(const char *name, float *variable) : name(name), integer(false), f(variable) {}; + Parameter(const char *name, int *variable) : name(name), integer(true), i(variable) {}; + float getValue() const { return integer ? *i : *f; }; + void setValue(const float value) { if (integer) *i = value; else *f = value; }; }; Parameter parameters[] = { @@ -84,10 +89,10 @@ void setupParameters() { // Read parameters from storage for (auto ¶meter : parameters) { if (!storage.isKey(parameter.name)) { - storage.putFloat(parameter.name, *parameter.variable); + storage.putFloat(parameter.name, parameter.getValue()); // store default value } - *parameter.variable = storage.getFloat(parameter.name, *parameter.variable); - parameter.value = *parameter.variable; + parameter.setValue(storage.getFloat(parameter.name, 0)); + parameter.cache = parameter.getValue(); } } @@ -102,13 +107,13 @@ const char *getParameterName(int index) { float getParameter(int index) { if (index < 0 || index >= parametersCount()) return NAN; - return *parameters[index].variable; + return parameters[index].getValue(); } float getParameter(const char *name) { for (auto ¶meter : parameters) { if (strcmp(parameter.name, name) == 0) { - return *parameter.variable; + return parameter.getValue(); } } return NAN; @@ -117,7 +122,8 @@ float getParameter(const char *name) { bool setParameter(const char *name, const float value) { for (auto ¶meter : parameters) { if (strcmp(parameter.name, name) == 0) { - *parameter.variable = value; + if (parameter.integer && !isfinite(value)) return false; // can't set integer to NaN or Inf + parameter.setValue(value); return true; } } @@ -130,16 +136,18 @@ void syncParameters() { if (motorsActive()) return; // don't use flash while flying, it may cause a delay for (auto ¶meter : parameters) { - if (parameter.value == *parameter.variable) continue; - if (isnan(parameter.value) && isnan(*parameter.variable)) continue; // handle NAN != NAN - storage.putFloat(parameter.name, *parameter.variable); - parameter.value = *parameter.variable; + if (parameter.getValue() == parameter.cache) continue; // no change + if (isnan(parameter.getValue()) && isnan(parameter.cache)) continue; // both are NaN + if (isinf(parameter.getValue()) && isinf(parameter.cache)) continue; // both are Inf + + storage.putFloat(parameter.name, parameter.getValue()); + parameter.cache = parameter.getValue(); // update cache } } void printParameters() { for (auto ¶meter : parameters) { - print("%s = %g\n", parameter.name, *parameter.variable); + print("%s = %g\n", parameter.name, parameter.getValue()); } }