Fix WS2812 led definition
[inav.git] / src / main / fc / settings.c
blob8dc17edc63119cd8c463279b022af19061fef0f5
1 #include <string.h>
2 #include <stdint.h>
4 #include "platform.h"
6 #include "common/string_light.h"
7 #include "common/utils.h"
9 #include "settings_generated.h"
11 #include "fc/settings.h"
13 #include "config/general_settings.h"
14 #include "flight/rpm_filter.h"
15 #include "settings_generated.c"
17 static bool settingGetWord(char *buf, int idx)
19 if (idx == 0) {
20 return false;
22 const uint8_t *ptr = settingNamesWords;
23 char *bufPtr = buf;
24 int used_bits = 0;
25 int word = 1;
26 for(;;) {
27 int shift = 8 - SETTINGS_WORDS_BITS_PER_CHAR - used_bits;
28 char chr;
29 if (shift > 0) {
30 chr = (*ptr >> shift) & (0xff >> (8 - SETTINGS_WORDS_BITS_PER_CHAR));
31 } else {
32 chr = (*ptr & (0xff >> (8 - (SETTINGS_WORDS_BITS_PER_CHAR + shift)))) << -shift;
33 ptr++;
34 chr |= (*ptr) >> (8 + shift);
36 if (word == idx) {
37 if (chr == 0) {
38 // Finished copying the word
39 *bufPtr++ = '\0';
40 break;
42 char c;
43 if (chr < 27) {
44 c = 'a' + (chr - 1);
45 } else {
46 c = wordSymbols[chr - 27];
48 *bufPtr++ = c;
49 } else {
50 if (chr == 0) {
51 // Word end
52 word++;
55 used_bits = (used_bits + SETTINGS_WORDS_BITS_PER_CHAR) % 8;
57 return true;
60 void settingGetName(const setting_t *val, char *buf)
62 uint8_t bpos = 0;
63 uint16_t n = 0;
64 char word[SETTING_MAX_WORD_LENGTH];
65 #ifndef SETTING_ENCODED_NAME_USES_BYTE_INDEXING
66 uint8_t shift = 0;
67 #endif
68 for (uint8_t ii = 0; ii < SETTING_ENCODED_NAME_MAX_BYTES; ii++) {
69 #ifdef SETTING_ENCODED_NAME_USES_BYTE_INDEXING
70 n = val->encoded_name[ii];
71 #else
72 // Decode a variable size uint
73 uint16_t b = val->encoded_name[ii];
74 if (b >= 0x80) {
75 // More bytes follow
76 n |= (b&0x7f) << shift;
77 shift += 7;
78 continue;
80 // Final byte
81 n |= b << shift;
82 #endif
83 if (!settingGetWord(word, n)) {
84 // No more words
85 break;
87 if (bpos > 0) {
88 // Word separator
89 buf[bpos++] = '_';
91 strcpy(&buf[bpos], word);
92 bpos += strlen(word);
93 #ifndef SETTING_ENCODED_NAME_USES_BYTE_INDEXING
94 // Reset shift and n
95 shift = 0;
96 n = 0;
97 #endif
99 buf[bpos] = '\0';
102 bool settingNameContains(const setting_t *val, char *buf, const char *cmdline)
104 settingGetName(val, buf);
105 return strstr(buf, cmdline) != NULL;
108 bool settingNameIsExactMatch(const setting_t *val, char *buf, const char *cmdline, uint8_t var_name_length)
110 settingGetName(val, buf);
111 return sl_strncasecmp(cmdline, buf, strlen(buf)) == 0 && var_name_length == strlen(buf);
114 const setting_t *settingFind(const char *name)
116 char buf[SETTING_MAX_NAME_LENGTH];
117 for (int ii = 0; ii < SETTINGS_TABLE_COUNT; ii++) {
118 const setting_t *setting = &settingsTable[ii];
119 settingGetName(setting, buf);
120 if (strcmp(buf, name) == 0) {
121 return setting;
124 return NULL;
127 const setting_t *settingGet(unsigned index)
129 return index < SETTINGS_TABLE_COUNT ? &settingsTable[index] : NULL;
132 unsigned settingGetIndex(const setting_t *val)
134 return val - settingsTable;
137 bool settingsValidate(unsigned *invalidIndex)
139 for (unsigned ii = 0; ii < SETTINGS_TABLE_COUNT; ii++) {
140 const setting_t *setting = settingGet(ii);
141 setting_min_t min = settingGetMin(setting);
142 setting_max_t max = settingGetMax(setting);
143 void *ptr = settingGetValuePointer(setting);
144 bool isValid = false;
145 switch (SETTING_TYPE(setting)) {
146 case VAR_UINT8:
148 uint8_t *value = ptr;
149 isValid = *value >= min && *value <= max;
150 break;
152 case VAR_INT8:
154 int8_t *value = ptr;
155 isValid = *value >= min && *value <= (int8_t)max;
156 break;
158 case VAR_UINT16:
160 uint16_t *value = ptr;
161 isValid = *value >= min && *value <= max;
162 break;
164 case VAR_INT16:
166 int16_t *value = ptr;
167 isValid = *value >= min && *value <= (int16_t)max;
168 break;
170 case VAR_UINT32:
172 uint32_t *value = ptr;
173 isValid = *value >= (uint32_t)min && *value <= max;
174 break;
176 case VAR_FLOAT:
178 float *value = ptr;
179 isValid = *value >= min && *value <= max;
180 break;
182 case VAR_STRING:
183 // We assume all strings are valid
184 isValid = true;
185 break;
187 if (!isValid) {
188 if (invalidIndex) {
189 *invalidIndex = ii;
191 return false;
194 return true;
197 size_t settingGetValueSize(const setting_t *val)
199 switch (SETTING_TYPE(val)) {
200 case VAR_UINT8:
201 FALLTHROUGH;
202 case VAR_INT8:
203 return 1;
204 case VAR_UINT16:
205 FALLTHROUGH;
206 case VAR_INT16:
207 return 2;
208 case VAR_UINT32:
209 FALLTHROUGH;
210 case VAR_FLOAT:
211 return 4;
212 case VAR_STRING:
213 return settingGetMax(val);
215 return 0; // Unreachable
218 pgn_t settingGetPgn(const setting_t *val)
220 uint16_t pos = val - (const setting_t *)settingsTable;
221 uint16_t acc = 0;
222 for (uint8_t ii = 0; ii < SETTINGS_PGN_COUNT; ii++) {
223 acc += settingsPgnCounts[ii];
224 if (acc > pos) {
225 return settingsPgn[ii];
228 return -1;
231 static uint16_t getValueOffset(const setting_t *value)
233 switch (SETTING_SECTION(value)) {
234 case MASTER_VALUE:
235 return value->offset;
236 case PROFILE_VALUE:
237 return value->offset + sizeof(pidProfile_t) * getConfigProfile();
238 case CONTROL_RATE_VALUE:
239 return value->offset + sizeof(controlRateConfig_t) * getConfigProfile();
240 case BATTERY_CONFIG_VALUE:
241 return value->offset + sizeof(batteryProfile_t) * getConfigBatteryProfile();
243 return 0;
246 void *settingGetValuePointer(const setting_t *val)
248 const pgRegistry_t *pg = pgFind(settingGetPgn(val));
249 return pg->address + getValueOffset(val);
252 const void * settingGetCopyValuePointer(const setting_t *val)
254 const pgRegistry_t *pg = pgFind(settingGetPgn(val));
255 return pg->copy + getValueOffset(val);
258 setting_min_t settingGetMin(const setting_t *val)
260 if (SETTING_MODE(val) == MODE_LOOKUP) {
261 return 0;
263 return settingMinMaxTable[SETTING_INDEXES_GET_MIN(val)];
266 setting_max_t settingGetMax(const setting_t *val)
268 if (SETTING_MODE(val) == MODE_LOOKUP) {
269 return settingLookupTables[val->config.lookup.tableIndex].valueCount - 1;
271 return settingMinMaxTable[SETTING_INDEXES_GET_MAX(val)];
274 const lookupTableEntry_t * settingLookupTable(const setting_t *val)
276 if (SETTING_MODE(val) == MODE_LOOKUP && val->config.lookup.tableIndex < LOOKUP_TABLE_COUNT) {
277 return &settingLookupTables[val->config.lookup.tableIndex];
279 return NULL;
282 const char * settingLookupValueName(const setting_t *val, unsigned v)
284 const lookupTableEntry_t *table = settingLookupTable(val);
285 if (table && v < table->valueCount) {
286 return table->values[v];
288 return NULL;
291 size_t settingGetValueNameMaxSize(const setting_t *val)
293 size_t maxSize = 0;
294 const lookupTableEntry_t *table = settingLookupTable(val);
295 if (table) {
296 for (unsigned ii = 0; ii < table->valueCount; ii++) {
297 maxSize = MAX(maxSize, strlen(table->values[ii]));
300 return maxSize;
303 const char * settingGetString(const setting_t *val)
305 if (SETTING_TYPE(val) == VAR_STRING) {
306 return settingGetValuePointer(val);
308 return NULL;
311 void settingSetString(const setting_t *val, const char *s, size_t size)
313 if (SETTING_TYPE(val) == VAR_STRING) {
314 char *p = settingGetValuePointer(val);
315 size_t copySize = MIN(size, settingGetMax(val));
316 memcpy(p, s, copySize);
317 p[copySize] = '\0';
321 setting_max_t settingGetStringMaxLength(const setting_t *val)
323 if (SETTING_TYPE(val) == VAR_STRING) {
324 // Max string length is stored as its max
325 return settingGetMax(val);
327 return 0;
330 bool settingsGetParameterGroupIndexes(pgn_t pg, uint16_t *start, uint16_t *end)
332 unsigned acc = 0;
333 for (int ii = 0; ii < SETTINGS_PGN_COUNT; ii++) {
334 if (settingsPgn[ii] == pg) {
335 if (start) {
336 *start = acc;
338 if (end) {
339 *end = acc + settingsPgnCounts[ii] - 1;
341 return true;
343 acc += settingsPgnCounts[ii];
345 return false;