|
23 | 23 | #include "tasks/mixer_task.h" |
24 | 24 | #include "hal/adc_driver.h" |
25 | 25 | #include "model_arena.h" |
| 26 | +#include "dataconstants.h" |
26 | 27 |
|
27 | 28 | #include "edgetx.h" |
28 | 29 |
|
| 30 | +#include <string.h> |
| 31 | + |
29 | 32 | static uint8_t _nb_expo_lines; |
30 | 33 |
|
31 | 34 | ExpoData* expoAddress(uint8_t idx) { |
@@ -81,7 +84,7 @@ void deleteExpo(uint8_t idx) |
81 | 84 | g_modelArena.deleteFromSection(ARENA_EXPOS, idx, sizeof(ExpoData)); |
82 | 85 |
|
83 | 86 | if (!isInputAvailable(input)) { |
84 | | - memclear(&g_model.inputNames[input], LEN_INPUT_NAME); |
| 87 | + inputNameClear(input); |
85 | 88 | } |
86 | 89 | mixerTaskStart(); |
87 | 90 |
|
@@ -174,3 +177,73 @@ void updateExpoCount() |
174 | 177 | { |
175 | 178 | _nb_expo_lines = _countExpoLines(); |
176 | 179 | } |
| 180 | + |
| 181 | +// --------------------------------------------------------------------------- |
| 182 | +// Input name accessors (arena-backed, sparse via side-array index) |
| 183 | +// --------------------------------------------------------------------------- |
| 184 | + |
| 185 | +#define INPUT_NAME_NO_SLOT 0xFF |
| 186 | + |
| 187 | +void inputNameIndexReset() |
| 188 | +{ |
| 189 | + memset(g_model.inputNameIndex, INPUT_NAME_NO_SLOT, |
| 190 | + sizeof(g_model.inputNameIndex)); |
| 191 | +} |
| 192 | + |
| 193 | +static inline char* _inputNameSlot(uint8_t slot) |
| 194 | +{ |
| 195 | + return reinterpret_cast<char*>( |
| 196 | + g_modelArena.sectionBase(ARENA_INPUT_NAMES)) + slot * LEN_INPUT_NAME; |
| 197 | +} |
| 198 | + |
| 199 | +const char* inputName(uint8_t input) |
| 200 | +{ |
| 201 | + uint8_t slot = g_model.inputNameIndex[input]; |
| 202 | + if (slot == INPUT_NAME_NO_SLOT) |
| 203 | + return nullptr; |
| 204 | + return _inputNameSlot(slot); |
| 205 | +} |
| 206 | + |
| 207 | +bool hasInputName(uint8_t input) |
| 208 | +{ |
| 209 | + return g_model.inputNameIndex[input] != INPUT_NAME_NO_SLOT; |
| 210 | +} |
| 211 | + |
| 212 | +char* inputNameAlloc(uint8_t input) |
| 213 | +{ |
| 214 | + uint8_t slot = g_model.inputNameIndex[input]; |
| 215 | + if (slot != INPUT_NAME_NO_SLOT) |
| 216 | + return _inputNameSlot(slot); |
| 217 | + |
| 218 | + // Append a new slot |
| 219 | + uint16_t count = g_modelArena.sectionCount(ARENA_INPUT_NAMES); |
| 220 | + if (!g_modelArena.ensureSectionCapacity(ARENA_INPUT_NAMES, count + 1)) |
| 221 | + return nullptr; |
| 222 | + |
| 223 | + g_model.inputNameIndex[input] = count; |
| 224 | + return _inputNameSlot(count); |
| 225 | +} |
| 226 | + |
| 227 | +void inputNameClear(uint8_t input) |
| 228 | +{ |
| 229 | + uint8_t slot = g_model.inputNameIndex[input]; |
| 230 | + if (slot == INPUT_NAME_NO_SLOT) |
| 231 | + return; |
| 232 | + |
| 233 | + uint16_t count = g_modelArena.sectionCount(ARENA_INPUT_NAMES); |
| 234 | + uint16_t lastSlot = count - 1; |
| 235 | + |
| 236 | + if (slot != lastSlot) { |
| 237 | + // Find which input owns the last slot and swap |
| 238 | + for (uint8_t i = 0; i < MAX_INPUTS; i++) { |
| 239 | + if (g_model.inputNameIndex[i] == lastSlot) { |
| 240 | + memcpy(_inputNameSlot(slot), _inputNameSlot(lastSlot), LEN_INPUT_NAME); |
| 241 | + g_model.inputNameIndex[i] = slot; |
| 242 | + break; |
| 243 | + } |
| 244 | + } |
| 245 | + } |
| 246 | + |
| 247 | + g_model.inputNameIndex[input] = INPUT_NAME_NO_SLOT; |
| 248 | + g_modelArena.trimSectionTo(ARENA_INPUT_NAMES, lastSlot); |
| 249 | +} |
0 commit comments