Bsongis/issue 5311 (#5354)

Fixes #5311
This commit is contained in:
Bertrand Songis
2017-11-13 22:17:13 +01:00
committed by GitHub
parent e6542a78d0
commit e5b2b8ef64
12 changed files with 166 additions and 68 deletions
+9 -1
View File
@@ -416,7 +416,7 @@ void evalFunctions()
else if (CFN_GVAR_MODE(cfn) == FUNC_ADJUST_GVAR_INCDEC) {
if (!(functionsContext.activeSwitches & switch_mask)) {
#if defined(CPUARM)
SET_GVAR(CFN_GVAR_INDEX(cfn), limit<int16_t>(CFN_GVAR_CST_MIN+g_model.gvars[CFN_GVAR_INDEX(cfn)].min, GVAR_VALUE(CFN_GVAR_INDEX(cfn), getGVarFlightMode(mixerCurrentFlightMode, CFN_GVAR_INDEX(cfn))) + CFN_PARAM(cfn), CFN_GVAR_CST_MAX-g_model.gvars[CFN_GVAR_INDEX(cfn)].max), mixerCurrentFlightMode);
SET_GVAR(CFN_GVAR_INDEX(cfn), limit<int16_t>(MODEL_GVAR_MIN(CFN_GVAR_INDEX(cfn)), GVAR_VALUE(CFN_GVAR_INDEX(cfn), getGVarFlightMode(mixerCurrentFlightMode, CFN_GVAR_INDEX(cfn))) + CFN_PARAM(cfn), MODEL_GVAR_MAX(CFN_GVAR_INDEX(cfn))), mixerCurrentFlightMode);
#else
SET_GVAR(CFN_GVAR_INDEX(cfn), GVAR_VALUE(CFN_GVAR_INDEX(cfn), getGVarFlightMode(mixerCurrentFlightMode, CFN_GVAR_INDEX(cfn))) + (CFN_PARAM(cfn) ? +1 : -1), mixerCurrentFlightMode);
#endif
@@ -429,12 +429,20 @@ void evalFunctions()
else if (CFN_PARAM(cfn) >= MIXSRC_REa && CFN_PARAM(cfn) < MIXSRC_TrimRud) {
int8_t scroll = rePreviousValues[CFN_PARAM(cfn)-MIXSRC_REa] - (rotencValue[CFN_PARAM(cfn)-MIXSRC_REa] / ROTARY_ENCODER_GRANULARITY);
if (scroll) {
#if defined(CPUARM)
SET_GVAR(CFN_GVAR_INDEX(cfn), limit<int16_t>(MODEL_GVAR_MIN(CFN_GVAR_INDEX(cfn)), GVAR_VALUE(CFN_GVAR_INDEX(cfn), getGVarFlightMode(mixerCurrentFlightMode, CFN_GVAR_INDEX(cfn))) + scroll, MODEL_GVAR_MAX(CFN_GVAR_INDEX(cfn))), mixerCurrentFlightMode);
#else
SET_GVAR(CFN_GVAR_INDEX(cfn), GVAR_VALUE(CFN_GVAR_INDEX(cfn), getGVarFlightMode(mixerCurrentFlightMode, CFN_GVAR_INDEX(cfn))) + scroll, mixerCurrentFlightMode);
#endif
}
}
#endif
else {
#if defined(CPUARM)
SET_GVAR(CFN_GVAR_INDEX(cfn), limit<int16_t>(MODEL_GVAR_MIN(CFN_GVAR_INDEX(cfn)), calcRESXto100(getValue(CFN_PARAM(cfn))), MODEL_GVAR_MAX(CFN_GVAR_INDEX(cfn))), mixerCurrentFlightMode);
#else
SET_GVAR(CFN_GVAR_INDEX(cfn), calcRESXto100(getValue(CFN_PARAM(cfn))), mixerCurrentFlightMode);
#endif
}
break;
#endif
+4 -2
View File
@@ -114,7 +114,7 @@ void menuModelGVarOne(event_t event)
}
}
void onGVARSMenu(const char *result)
void onGVARSMenu(const char * result)
{
int sub = menuVerticalPosition;
@@ -165,16 +165,18 @@ void menuModelGVars(event_t event)
LcdFlags attr = ((sub == i && menuHorizontalPosition == j) ? (s_editMode > 0 ? BLINK | INVERS : INVERS) : 0);
coord_t x = GVARS_FM_COLUMN(j);
coord_t yval = y;
if (v > GVAR_MAX) {
attr |= SMLSIZE;
}
else if (g_model.gvars[i].prec > 0 || abs(v) >= 100) {
attr |= TINSIZE | NO_UNIT;
++yval;
}
else {
attr |= SMLSIZE | NO_UNIT;
}
editGVarValue(x, y, event, i, j, attr);
editGVarValue(x, yval, event, i, j, attr);
}
}
@@ -174,7 +174,7 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF
drawStringWithIndex(0, y, functions == g_model.customFn ? STR_SF : STR_GF, k+1, (sub==k && menuHorizontalPosition<0) ? INVERS : 0);
CustomFunctionData *cfn = &functions[k];
CustomFunctionData * cfn = &functions[k];
uint8_t func = CFN_FUNC(cfn);
for (uint8_t j=0; j<5; j++) {
uint8_t attr = ((sub==k && menuHorizontalPosition==j) ? ((s_editMode>0) ? BLINK|INVERS : INVERS) : 0);
@@ -344,10 +344,14 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF
else if (func == FUNC_ADJUST_GVAR) {
switch (CFN_GVAR_MODE(cfn)) {
case FUNC_ADJUST_GVAR_CONSTANT:
{
uint8_t gvar_index = CFN_GVAR_INDEX(cfn);
val_displayed = (int16_t)CFN_PARAM(cfn);
val_min = CFN_GVAR_CST_MIN; val_max = CFN_GVAR_CST_MAX;
lcdDrawNumber(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr|LEFT);
val_min = max<int16_t>(CFN_GVAR_CST_MIN, MODEL_GVAR_MIN(gvar_index));
val_max = min<int16_t>(CFN_GVAR_CST_MAX, MODEL_GVAR_MAX(gvar_index));
drawGVarValue(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, gvar_index, val_displayed, attr|LEFT);
break;
}
case FUNC_ADJUST_GVAR_SOURCE:
val_max = MIXSRC_LAST_CH;
drawSource(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr);
+118 -53
View File
@@ -20,17 +20,103 @@
#include "opentx.h"
void editGVarValue(coord_t x, coord_t y, event_t event, uint8_t gvar, uint8_t flightMode, LcdFlags flags)
{
FlightModeData * fm = &g_model.flightModeData[flightMode];
gvar_t & v = fm->gvars[gvar];
int16_t vmin, vmax;
if (v > GVAR_MAX) {
uint8_t fm = v - GVAR_MAX - 1;
if (fm >= flightMode) fm++;
drawFlightMode(x, y, fm + 1, flags&(~LEFT));
vmin = GVAR_MAX + 1;
vmax = GVAR_MAX + MAX_FLIGHT_MODES - 1;
}
else {
drawGVarValue(x, y, gvar, v, flags);
vmin = GVAR_MIN + g_model.gvars[gvar].min;
vmax = GVAR_MAX - g_model.gvars[gvar].max;
}
if (flags & INVERS) {
if (event == EVT_KEY_LONG(KEY_ENTER) && flightMode > 0) {
v = (v > GVAR_MAX ? 0 : GVAR_MAX+1);
storageDirty(EE_MODEL);
}
else if (s_editMode > 0) {
v = checkIncDec(event, v, vmin, vmax, EE_MODEL);
}
}
}
enum GVarFields {
GVAR_FIELD_NAME,
GVAR_FIELD_UNIT,
GVAR_FIELD_PREC,
GVAR_FIELD_MIN,
GVAR_FIELD_MAX,
GVAR_FIELD_FM0,
GVAR_FIELD_LAST = GVAR_FIELD_FM0 + MAX_FLIGHT_MODES
};
bool menuModelGVarOne(event_t event)
{
SIMPLE_SUBMENU(STR_GVARS, ICON_MODEL_GVARS, GVAR_FIELD_LAST);
GVarData * gvar = &g_model.gvars[s_currIdx];
drawStringWithIndex(50, 3+FH, STR_GV, s_currIdx+1, MENU_TITLE_COLOR, NULL, "=");
drawGVarValue(lcdNextPos + 2, 3+FH, s_currIdx, getGVarValue(s_currIdx, getFlightMode()), LEFT | MENU_TITLE_COLOR);
for (int i=0; i<NUM_BODY_LINES+1; i++) {
coord_t y = MENU_CONTENT_TOP - FH - 2 + i*FH;
int k = i + menuVerticalOffset;
LcdFlags attr = (menuVerticalPosition == k ? (s_editMode > 0 ? BLINK | INVERS : INVERS) : 0);
switch (k) {
case GVAR_FIELD_NAME:
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_NAME);
editName(MIXES_2ND_COLUMN, y, gvar->name, LEN_GVAR_NAME, event, attr);
break;
case GVAR_FIELD_UNIT:
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_UNIT);
gvar->unit = editChoice(MIXES_2ND_COLUMN, y, "\001-%", gvar->unit, 0, 1, attr, event);
break;
case GVAR_FIELD_PREC:
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_PRECISION);
gvar->prec = editChoice(MIXES_2ND_COLUMN, y, STR_VPREC, gvar->prec, 0, 1, attr, event);
break;
case GVAR_FIELD_MIN:
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MIN);
drawGVarValue(MIXES_2ND_COLUMN, y, s_currIdx, GVAR_MIN+gvar->min, LEFT|attr);
if (attr) gvar->min = checkIncDec(event, GVAR_MIN+gvar->min, GVAR_MIN, GVAR_MAX-gvar->max, EE_MODEL) - GVAR_MIN;
break;
case GVAR_FIELD_MAX:
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MAX);
drawGVarValue(MIXES_2ND_COLUMN, y, s_currIdx, GVAR_MAX-gvar->max, LEFT|attr);
if (attr) gvar->max = GVAR_MAX - checkIncDec(event, GVAR_MAX-gvar->max, GVAR_MIN+gvar->min, GVAR_MAX, EE_MODEL);
break;
default:
drawStringWithIndex(MENUS_MARGIN_LEFT, y, STR_FP, k-GVAR_FIELD_FM0);
editGVarValue(MIXES_2ND_COLUMN, y, event, s_currIdx, k-GVAR_FIELD_FM0, LEFT|attr);
break;
}
}
return true;
}
void onGVARSMenu(const char * result)
{
int8_t sub = menuVerticalPosition;
int sub = menuVerticalPosition;
if (result == STR_ENABLE_POPUP) {
g_model.gvars[sub].popup = true;
storageDirty(EE_MODEL);
}
else if (result == STR_DISABLE_POPUP) {
g_model.gvars[sub].popup = false;
storageDirty(EE_MODEL);
if (result == STR_EDIT) {
s_currIdx = sub;
pushMenu(menuModelGVarOne);
}
else if (result == STR_CLEAR) {
for (int i=0; i<MAX_FLIGHT_MODES; i++) {
@@ -40,11 +126,12 @@ void onGVARSMenu(const char * result)
}
}
#define GVARS_FM_COLUMN(p) (150 + (p)*41)
#define GVARS_FM_COLUMN(p) (127 + (p)*44)
#define GVAR_MAX_COLUMNS (NAVIGATION_LINE_BY_LINE|(MAX_FLIGHT_MODES-1))
bool menuModelGVars(event_t event)
{
MENU(STR_MENUGLOBALVARS, MODEL_ICONS, menuTabModel, MENU_MODEL_GVARS/* TODO, first2seconds ? CHECK_FLAG_NO_SCREEN_INDEX : 0*/, MAX_GVARS, { NAVIGATION_LINE_BY_LINE|MAX_FLIGHT_MODES, NAVIGATION_LINE_BY_LINE|MAX_FLIGHT_MODES, NAVIGATION_LINE_BY_LINE|MAX_FLIGHT_MODES, NAVIGATION_LINE_BY_LINE|MAX_FLIGHT_MODES, NAVIGATION_LINE_BY_LINE|MAX_FLIGHT_MODES, NAVIGATION_LINE_BY_LINE|MAX_FLIGHT_MODES, NAVIGATION_LINE_BY_LINE|MAX_FLIGHT_MODES, NAVIGATION_LINE_BY_LINE|MAX_FLIGHT_MODES, NAVIGATION_LINE_BY_LINE|MAX_FLIGHT_MODES});
MENU(STR_MENUGLOBALVARS, MODEL_ICONS, menuTabModel, MENU_MODEL_GVARS/* TODO, first2seconds ? CHECK_FLAG_NO_SCREEN_INDEX : 0*/, MAX_GVARS, { GVAR_MAX_COLUMNS, GVAR_MAX_COLUMNS, GVAR_MAX_COLUMNS, GVAR_MAX_COLUMNS, GVAR_MAX_COLUMNS, GVAR_MAX_COLUMNS, GVAR_MAX_COLUMNS, GVAR_MAX_COLUMNS, GVAR_MAX_COLUMNS});
int sub = menuVerticalPosition;
int curfm = getFlightMode();
@@ -56,61 +143,39 @@ bool menuModelGVars(event_t event)
#endif
for (uint8_t l=0; l<NUM_BODY_LINES; l++) {
int i = l+menuVerticalOffset;
int i = l + menuVerticalOffset;
coord_t y = MENU_CONTENT_TOP + l*FH;
if (g_model.gvars[i].popup) {
lcdDrawText(MENUS_MARGIN_LEFT+25, y, "!");
}
drawStringWithIndex(MENUS_MARGIN_LEFT, y, STR_GV, i+1, ((sub==i && menuHorizontalPosition<0) ? INVERS : 0));
for (uint8_t j=0; j<1+MAX_FLIGHT_MODES; j++) {
LcdFlags attr = ((sub==i && menuHorizontalPosition==j) ? ((s_editMode>0) ? BLINK|INVERS : INVERS) : 0);
coord_t x = GVARS_FM_COLUMN(j-1);
switch (j) {
case 0:
editName(MENUS_MARGIN_LEFT+50, y, g_model.gvars[i].name, LEN_GVAR_NAME, event, attr);
break;
drawStringWithIndex(MENUS_MARGIN_LEFT-3, y, STR_GV, i+1, ((sub==i && menuHorizontalPosition<0) ? INVERS : 0));
lcdDrawSizedText(MENUS_MARGIN_LEFT+35, y, g_model.gvars[i].name, LEN_GVAR_NAME, ZCHAR);
default:
{
uint16_t flightMode = j-1;
FlightModeData * fm = &g_model.flightModeData[flightMode];
int16_t & v = fm->gvars[i];
int16_t vmin, vmax;
if (v > GVAR_MAX) {
uint8_t p = v - GVAR_MAX - 1;
if (p >= flightMode) p++;
drawFlightMode(x, y, p+1, attr | RIGHT | ((flightMode == curfm) ? BOLD : 0));
vmin = GVAR_MAX+1; vmax = GVAR_MAX+MAX_FLIGHT_MODES-1;
}
else {
if (abs(v) >= 1000)
lcdDrawNumber(x, y+1, v, TINSIZE|attr|RIGHT);
else
lcdDrawNumber(x, y, v, attr | RIGHT | ((flightMode == curfm) ? BOLD : 0));
vmin = -GVAR_MAX; vmax = GVAR_MAX;
}
if (attr) {
if (event == EVT_KEY_LONG(KEY_ENTER) && flightMode > 0) {
v = (v > GVAR_MAX ? 0 : GVAR_MAX+1);
storageDirty(EE_MODEL);
}
else if (s_editMode>0) {
v = checkIncDec(event, v, vmin, vmax, EE_MODEL);
}
}
break;
}
for (int j=0; j<MAX_FLIGHT_MODES; j++) {
FlightModeData * fm = &g_model.flightModeData[j];
gvar_t v = fm->gvars[i];
LcdFlags attr = RIGHT | ((sub == i && menuHorizontalPosition == j) ? (s_editMode > 0 ? BLINK | INVERS : INVERS) : 0);
if (j == curfm)
attr |= BOLD;
coord_t x = GVARS_FM_COLUMN(j);
coord_t yval = y;
if (v <= GVAR_MAX && (g_model.gvars[i].prec > 0 || abs(v) >= 1000 || ( abs(v) >= 100 && g_model.gvars[i].unit > 0))) {
attr |= SMLSIZE;
yval += 2;
}
if (v <= GVAR_MAX && g_model.gvars[i].unit > 0) {
x -= 9;
lcdDrawText(GVARS_FM_COLUMN(j) - 9, y+5, "%", TINSIZE);
}
editGVarValue(x, yval, event, i, j, attr | NO_UNIT);
}
}
if (menuHorizontalPosition < 0 && event==EVT_KEY_LONG(KEY_ENTER)) {
killEvents(event);
if (g_model.gvars[sub].popup)
POPUP_MENU_ADD_ITEM(STR_DISABLE_POPUP);
else
POPUP_MENU_ADD_ITEM(STR_ENABLE_POPUP);
POPUP_MENU_ADD_ITEM(STR_EDIT);
POPUP_MENU_ADD_ITEM(STR_CLEAR);
POPUP_MENU_START(onGVARSMenu);
}
+2 -2
View File
@@ -153,7 +153,7 @@ enum MixFields {
MIX_FIELD_OFFSET,
MIX_FIELD_TRIM,
CASE_CURVES(MIX_FIELD_CURVE)
CASE_FLIGHT_MODES(MIX_FIELD_FLIGHT_PHASE)
CASE_FLIGHT_MODES(MIX_FIELD_FLIGHT_MODE)
MIX_FIELD_SWITCH,
// MIX_FIELD_WARNING,
MIX_FIELD_MLTPX,
@@ -235,7 +235,7 @@ bool menuModelMixOne(event_t event)
break;
#endif
#if defined(FLIGHT_MODES)
case MIX_FIELD_FLIGHT_PHASE:
case MIX_FIELD_FLIGHT_MODE:
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_FLMODE);
md2->flightModes = editFlightModes(MIXES_2ND_COLUMN, y, event, md2->flightModes, attr);
break;
@@ -340,10 +340,14 @@ bool menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF
else if (func == FUNC_ADJUST_GVAR) {
switch (CFN_GVAR_MODE(cfn)) {
case FUNC_ADJUST_GVAR_CONSTANT:
val_displayed = (int16_t)CFN_PARAM(cfn);
val_min = -CFN_GVAR_CST_MAX; val_max = +CFN_GVAR_CST_MAX;
lcdDrawNumber(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr|LEFT);
{
uint8_t gvar_index = CFN_GVAR_INDEX(cfn);
val_displayed = (int16_t) CFN_PARAM(cfn);
val_min = max<int16_t>(CFN_GVAR_CST_MIN, MODEL_GVAR_MIN(gvar_index));
val_max = min<int16_t>(CFN_GVAR_CST_MAX, MODEL_GVAR_MAX(gvar_index));
drawGVarValue(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, gvar_index, val_displayed, attr|LEFT);
break;
}
case FUNC_ADJUST_GVAR_SOURCE:
val_max = MIXSRC_LAST_CH;
drawSource(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr);
@@ -362,7 +366,7 @@ bool menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF
lcdDrawText(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, "-= ", attr);
else
lcdDrawText(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, "+= ", attr);
lcdDrawNumber(lcdNextPos, y, abs(val_displayed), attr|LEFT);
drawGVarValue(lcdNextPos, y, CFN_GVAR_INDEX(cfn), abs(val_displayed), attr|LEFT);
break;
}
}
+9
View File
@@ -314,6 +314,15 @@ bool noZero(int val)
return val != 0;
}
void drawGVarValue(coord_t x, coord_t y, uint8_t gvar, gvar_t value, LcdFlags flags)
{
uint8_t prec = g_model.gvars[gvar].prec;
if (prec > 0) {
flags |= (prec == 1 ? PREC1 : PREC2);
}
drawValueWithUnit(x, y, value, g_model.gvars[gvar].unit ? UNIT_PERCENT : UNIT_RAW, flags);
}
int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t editflags, event_t event)
{
uint16_t delta = GV_GET_GV1_VALUE(max);
+2
View File
@@ -59,6 +59,8 @@ void drawHorizontalSlider(coord_t x, coord_t y, int len, int val, int min, int m
void drawSlider(coord_t x, coord_t y, int len, int val, int min, int max, uint8_t steps, uint32_t options);
#define drawStatusLine(...)
void drawGVarValue(coord_t x, coord_t y, uint8_t gvar, gvar_t value, LcdFlags flags);
#if defined(GVARS)
int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t editflags, event_t event);
#else
+3 -1
View File
@@ -20,12 +20,14 @@
#include "opentx.h"
void drawStringWithIndex(coord_t x, coord_t y, const char * str, int idx, LcdFlags flags, const char * prefix)
void drawStringWithIndex(coord_t x, coord_t y, const char * str, int idx, LcdFlags flags, const char * prefix, const char * suffix)
{
char s[64];
char * tmp = (prefix ? strAppend(s, prefix) : s);
tmp = strAppend(tmp, str);
tmp = strAppendUnsigned(tmp, abs(idx));
if (suffix)
strAppend(tmp, suffix);
lcdDrawText(x, y, s, flags);
}
+1 -1
View File
@@ -105,7 +105,7 @@ void drawSourceValue(coord_t x, coord_t y, source_t channel, LcdFlags flags=0);
void drawCurve(coord_t offset=0);
#if defined(COLORLCD)
void drawStringWithIndex(coord_t x, coord_t y, const char * str, int idx, LcdFlags flags=0, const char * prefix=NULL);
void drawStringWithIndex(coord_t x, coord_t y, const char * str, int idx, LcdFlags flags=0, const char * prefix=NULL, const char * suffix=NULL);
int editChoice(coord_t x, coord_t y, const char * values, int value, int min, int max, LcdFlags flags, event_t event);
uint8_t editCheckBox(uint8_t value, coord_t x, coord_t y, LcdFlags flags, event_t event);
swsrc_t editSwitch(coord_t x, coord_t y, swsrc_t value, LcdFlags flags, event_t event);
+2
View File
@@ -107,6 +107,8 @@
#define CFN_RESET(p) ((p)->active=0, (p)->clear.val1=0, (p)->clear.val2=0)
#define CFN_GVAR_CST_MIN -GVAR_MAX
#define CFN_GVAR_CST_MAX GVAR_MAX
#define MODEL_GVAR_MIN(idx) (CFN_GVAR_CST_MIN + g_model.gvars[idx].min)
#define MODEL_GVAR_MAX(idx) (CFN_GVAR_CST_MAX - g_model.gvars[idx].max)
#elif defined(CPUM2560)
#define CFN_SWITCH(p) ((p)->swtch)
#define CFN_FUNC(p) ((p)->func)
+1 -1
View File
@@ -900,7 +900,7 @@ extern const pm_char STR_BLCOLOR[];
#define TR_LIMITS_HEADERS { HINT(TR_LIMITS_HEADERS_NAME), HINT(TR_LIMITS_HEADERS_SUBTRIM), HINT(TR_LIMITS_HEADERS_MIN), HINT(TR_LIMITS_HEADERS_MAX), HINT(TR_LIMITS_HEADERS_DIRECTION), HINT(TR_LIMITS_HEADERS_CURVE), HINT(TR_LIMITS_HEADERS_PPMCENTER), HINT(TR_LIMITS_HEADERS_SUBTRIMMODE) }
#define TR_LSW_HEADERS { HINT(TR_LSW_HEADERS_FUNCTION), HINT(TR_LSW_HEADERS_V1), HINT(TR_LSW_HEADERS_V2), HINT(TR_LSW_HEADERS_V2), HINT(TR_LSW_HEADERS_ANDSW), HINT(TR_LSW_HEADERS_DURATION), HINT(TR_LSW_HEADERS_DELAY) }
#define TR_GVAR_HEADERS { HINT(TR_GVAR_HEADERS_NAME), HINT(TR_GVAR_HEADERS_FM0), HINT(TR_GVAR_HEADERS_FM1), HINT(TR_GVAR_HEADERS_FM2), HINT(TR_GVAR_HEADERS_FM3), HINT(TR_GVAR_HEADERS_FM4), HINT(TR_GVAR_HEADERS_FM5), HINT(TR_GVAR_HEADERS_FM6), HINT(TR_GVAR_HEADERS_FM7), HINT(TR_GVAR_HEADERS_FM8) }
#define TR_GVAR_HEADERS { HINT(TR_GVAR_HEADERS_FM0), HINT(TR_GVAR_HEADERS_FM1), HINT(TR_GVAR_HEADERS_FM2), HINT(TR_GVAR_HEADERS_FM3), HINT(TR_GVAR_HEADERS_FM4), HINT(TR_GVAR_HEADERS_FM5), HINT(TR_GVAR_HEADERS_FM6), HINT(TR_GVAR_HEADERS_FM7), HINT(TR_GVAR_HEADERS_FM8) }
#if LCD_W >= 212
extern const char * const STR_PHASES_HEADERS[];