diff --git a/companion/src/firmwares/opentx/opentxGruvin9xsimulator.cpp b/companion/src/firmwares/opentx/opentxGruvin9xsimulator.cpp index a75922053..d3b6f8c8e 100644 --- a/companion/src/firmwares/opentx/opentxGruvin9xsimulator.cpp +++ b/companion/src/firmwares/opentx/opentxGruvin9xsimulator.cpp @@ -75,6 +75,7 @@ namespace Open9xGruvin9x { #include "radio/src/vario.cpp" #include "radio/src/gui/menus.cpp" #include "radio/src/gui/menu_model.cpp" +#include "radio/src/gui/menu_model_curves.cpp" #include "radio/src/gui/menu_model_limits.cpp" #include "radio/src/gui/menu_model_telemetry.cpp" #include "radio/src/gui/menu_general.cpp" diff --git a/companion/src/firmwares/opentx/opentxM128simulator.cpp b/companion/src/firmwares/opentx/opentxM128simulator.cpp index d0fb6afe5..caebb982f 100644 --- a/companion/src/firmwares/opentx/opentxM128simulator.cpp +++ b/companion/src/firmwares/opentx/opentxM128simulator.cpp @@ -76,6 +76,7 @@ namespace OpenTxM128 { #include "radio/src/vario.cpp" #include "radio/src/gui/menus.cpp" #include "radio/src/gui/menu_model.cpp" +#include "radio/src/gui/menu_model_curves.cpp" #include "radio/src/gui/menu_model_limits.cpp" #include "radio/src/gui/menu_model_telemetry.cpp" #include "radio/src/gui/menu_general.cpp" diff --git a/companion/src/firmwares/opentx/opentxM64simulator.cpp b/companion/src/firmwares/opentx/opentxM64simulator.cpp index af8126807..4eb8e551a 100644 --- a/companion/src/firmwares/opentx/opentxM64simulator.cpp +++ b/companion/src/firmwares/opentx/opentxM64simulator.cpp @@ -81,6 +81,7 @@ namespace OpenTxM64 { #include "radio/src/vario.cpp" #include "radio/src/gui/menus.cpp" #include "radio/src/gui/menu_model.cpp" +#include "radio/src/gui/menu_model_curves.cpp" #include "radio/src/gui/menu_model_limits.cpp" #include "radio/src/gui/menu_model_telemetry.cpp" #include "radio/src/gui/menu_general.cpp" diff --git a/companion/src/firmwares/opentx/opentxSky9xsimulator.cpp b/companion/src/firmwares/opentx/opentxSky9xsimulator.cpp index b4a454a7e..cfa17035c 100644 --- a/companion/src/firmwares/opentx/opentxSky9xsimulator.cpp +++ b/companion/src/firmwares/opentx/opentxSky9xsimulator.cpp @@ -90,6 +90,7 @@ namespace Open9xSky9x { #include "radio/src/vario.cpp" #include "radio/src/gui/menus.cpp" #include "radio/src/gui/menu_model.cpp" +#include "radio/src/gui/menu_model_curves.cpp" #include "radio/src/gui/menu_model_limits.cpp" #include "radio/src/gui/menu_model_telemetry.cpp" #include "radio/src/gui/menu_general.cpp" diff --git a/companion/src/firmwares/opentx/opentxTaranisSimulator.cpp b/companion/src/firmwares/opentx/opentxTaranisSimulator.cpp index a9c303208..e78c4edd8 100644 --- a/companion/src/firmwares/opentx/opentxTaranisSimulator.cpp +++ b/companion/src/firmwares/opentx/opentxTaranisSimulator.cpp @@ -96,6 +96,7 @@ inline int geteepromsize() { #include "radio/src/vario.cpp" #include "radio/src/gui/menus.cpp" #include "radio/src/gui/menu_model.cpp" +#include "radio/src/gui/menu_model_curves.cpp" #include "radio/src/gui/menu_model_custom_scripts.cpp" #include "radio/src/gui/menu_model_limits.cpp" #include "radio/src/gui/menu_model_telemetry.cpp" diff --git a/companion/src/firmwares/opentx/opentxTaranisX9ESimulator.cpp b/companion/src/firmwares/opentx/opentxTaranisX9ESimulator.cpp index c50a66de2..2fbd80be1 100755 --- a/companion/src/firmwares/opentx/opentxTaranisX9ESimulator.cpp +++ b/companion/src/firmwares/opentx/opentxTaranisX9ESimulator.cpp @@ -98,6 +98,7 @@ inline int geteepromsize() { #include "radio/src/vario.cpp" #include "radio/src/gui/menus.cpp" #include "radio/src/gui/menu_model.cpp" +#include "radio/src/gui/menu_model_curves.cpp" #include "radio/src/gui/menu_model_custom_scripts.cpp" #include "radio/src/gui/menu_model_limits.cpp" #include "radio/src/gui/menu_model_telemetry.cpp" diff --git a/radio/src/Makefile b/radio/src/Makefile index 079ee9636..76c447cff 100644 --- a/radio/src/Makefile +++ b/radio/src/Makefile @@ -1016,6 +1016,7 @@ endif ifeq ($(CURVES), YES) CPPDEFS += -DCURVES + GUIMODELSRC += gui/menu_model_curves.cpp endif ifeq ($(GVARS), YES) diff --git a/radio/src/gui/menu_model.cpp b/radio/src/gui/menu_model.cpp index 026c1f19f..6665128ff 100644 --- a/radio/src/gui/menu_model.cpp +++ b/radio/src/gui/menu_model.cpp @@ -72,6 +72,7 @@ void menuModelExposAll(uint8_t event); void menuModelMixAll(uint8_t event); void menuModelLimits(uint8_t event); void menuModelCurvesAll(uint8_t event); +void menuModelCurveOne(uint8_t event); void menuModelGVars(uint8_t event); void menuModelLogicalSwitches(uint8_t event); void menuModelCustomFunctions(uint8_t event); @@ -80,6 +81,12 @@ void menuModelTelemetry(uint8_t event); void menuModelTemplates(uint8_t event); void menuModelExpoOne(uint8_t event); +extern uint8_t s_curveChan; + +#if defined(PCBTARANIS) +void editCurveRef(coord_t x, coord_t y, CurveRef & curve, uint8_t event, uint8_t attr); +#endif + const MenuFuncP_PROGMEM menuTabModel[] PROGMEM = { menuModelSelect, menuModelSetup, @@ -2434,420 +2441,6 @@ void DrawFunction(FnFuncP fn, uint8_t offset=0) } } -#if defined(CURVES) -static uint8_t s_curveChan; -int16_t curveFn(int16_t x) -{ - return applyCustomCurve(x, s_curveChan); -} - -struct point_t { - coord_t x; - coord_t y; -}; - -point_t getPoint(uint8_t i) -{ - point_t result = {0, 0}; -#if defined(PCBTARANIS) - CurveInfo &crv = g_model.curves[s_curveChan]; - int8_t *points = curveAddress(s_curveChan); - bool custom = (crv.type == CURVE_TYPE_CUSTOM); - uint8_t count = 5+crv.points; -#else - CurveInfo crv = curveInfo(s_curveChan); - int8_t *points = crv.crv; - bool custom = crv.custom; - uint8_t count = crv.points; -#endif - if (i < count) { -#if defined(PCBTARANIS) - result.x = X0-1-WCHART+i*WCHART*2/(count-1); -#else - result.x = X0-1-WCHART+i*WCHART/(count/2); -#endif - result.y = (LCD_H-1) - (100 + points[i]) * (LCD_H-1) / 200; - if (custom && i>0 && i g_model.points + sizeof(g_model.points)) { - AUDIO_WARNING2(); - return false; - } - - int8_t *nextCrv = curveAddress(index+1); - memmove(nextCrv+shift, nextCrv, 5*(MAX_CURVES-index-1)+curveEnd[MAX_CURVES-1]-curveEnd[index]); - if (shift < 0) memclear(&g_model.points[NUM_POINTS-1] + shift, -shift); - while (index NUM_POINTS-5*MAX_CURVES) { - AUDIO_WARNING2(); - return false; - } - - int8_t *crv = curveAddress(index); - if (shift < 0) { - for (uint8_t i=0; i0 ? INVERS|BLINK : INVERS) : 0); - lcd_putsLeft(3*FH+1, STR_TYPE); - lcd_putsiAtt(INDENT_WIDTH, 4*FH+1, STR_CURVE_TYPES, crv.type, attr); - if (attr) { - uint8_t newType = checkIncDecModelZero(event, crv.type, CURVE_TYPE_LAST); - if (newType != crv.type) { - for (int i=1; i<4+crv.points; i++) - points[i] = calcRESXto100(applyCustomCurve(calc100toRESX(-100 + i*200/(4+crv.points)), s_curveChan)); - moveCurve(s_curveChan, checkIncDec_Ret > 0 ? 3+crv.points : -3-crv.points); - if (newType == CURVE_TYPE_CUSTOM) { - for (int i=0; i<3+crv.points; i++) - points[5+crv.points+i] = -100 + ((i+1)*200) / (4+crv.points); - } - crv.type = newType; - } - } - - attr = (m_posVert==2 ? (s_editMode>0 ? INVERS|BLINK : INVERS) : 0); - lcd_putsLeft(5*FH+1, STR_COUNT); - lcd_outdezAtt(INDENT_WIDTH, 6*FH+1, 5+crv.points, LEFT|attr); - lcd_putsAtt(lcdLastPos, 6*FH+1, STR_PTS, attr); - if (attr) { - int8_t count = checkIncDecModel(event, crv.points, -3, 12); // 2pts - 17pts - if (checkIncDec_Ret) { - int8_t newPoints[MAX_POINTS]; - newPoints[0] = points[0]; - newPoints[4+count] = points[4+crv.points]; - for (int i=1; i<4+count; i++) - newPoints[i] = calcRESXto100(applyCustomCurve(calc100toRESX(-100 + (i*200) / (4+count)), s_curveChan)); - moveCurve(s_curveChan, checkIncDec_Ret*(crv.type==CURVE_TYPE_CUSTOM?2:1)); - for (int i=0; i<5+count; i++) { - points[i] = newPoints[i]; - if (crv.type == CURVE_TYPE_CUSTOM && i!=0 && i!=4+count) - points[5+count+i-1] = -100 + (i*200) / (4+count); - } - crv.points = count; - } - } - - lcd_putsLeft(7*FH+1, STR_SMOOTH); - menu_lcd_onoff(7*FW, 7*FH+1, crv.smooth, m_posVert==3 ? INVERS : 0); - if (m_posVert==3) crv.smooth = checkIncDecModel(event, crv.smooth, 0, 1); - - switch(event) { - case EVT_ENTRY: - pointsOfs = 0; - SET_SCROLLBAR_X(0); - break; - case EVT_KEY_LONG(KEY_ENTER): - if (m_posVert > 1) { - killEvents(event); - MENU_ADD_ITEM(STR_CURVE_PRESET); - MENU_ADD_ITEM(STR_MIRROR); - MENU_ADD_ITEM(STR_CLEAR); - menuHandler = onCurveOneMenu; - } - break; - case EVT_KEY_LONG(KEY_MENU): - pushMenu(menuChannelsView); - killEvents(event); - } - - DrawCurve(FW); - - uint8_t posY = FH+1; - attr = (s_editMode > 0 ? INVERS|BLINK : INVERS); - for (uint8_t i=0; i<5+crv.points; i++) { - point_t point = getPoint(i); - uint8_t selectionMode = 0; - if (crv.type==CURVE_TYPE_CUSTOM) { - if (m_posVert==4+2*i || (i==5+crv.points-1 && m_posVert==4+5+crv.points+5+crv.points-2-1)) - selectionMode = 2; - else if (i>0 && m_posVert==3+2*i) - selectionMode = 1; - } - else if (m_posVert == 4+i) { - selectionMode = 2; - } - - if (i>=pointsOfs && i0 && i<5+crv.points-1) x = points[5+crv.points+i-1]; - lcd_outdezAtt(6+8*FW, posY, i+1, LEFT); - lcd_outdezAtt(3+12*FW, posY, x, LEFT|(selectionMode==1?attr:0)); - lcd_outdezAtt(3+16*FW, posY, points[i], LEFT|(selectionMode==2?attr:0)); - posY += FH; - } - - if (selectionMode > 0) { - // do selection square - lcd_filled_rect(point.x-FW-1, point.y-2, 5, 5, SOLID, FORCE); - lcd_filled_rect(point.x-FW, point.y-1, 3, 3, SOLID); - if (s_editMode > 0) { - if (selectionMode == 1) - CHECK_INCDEC_MODELVAR(event, points[5+crv.points+i-1], i==1 ? -100 : points[5+crv.points+i-2], i==5+crv.points-2 ? 100 : points[5+crv.points+i]); // edit X - else if (selectionMode == 2) - CHECK_INCDEC_MODELVAR(event, points[i], -100, 100); - } - if (i < pointsOfs) - pointsOfs = i; - else if (i > pointsOfs+6) - pointsOfs = i-6; - } - } -} -#else -void menuModelCurveOne(uint8_t event) -{ - TITLE(STR_MENUCURVE); - lcd_outdezAtt(PSIZE(TR_MENUCURVE)*FW+1, 0, s_curveChan+1, INVERS|LEFT); - DISPLAY_PROGRESS_BAR(20*FW+1); - - CurveInfo crv = curveInfo(s_curveChan); - - switch(event) { - case EVT_ENTRY: - s_editMode = 1; - break; - CASE_EVT_ROTARY_BREAK - case EVT_KEY_BREAK(KEY_ENTER): - if (s_editMode <= 0) - m_posHorz = 0; - if (s_editMode == 1 && crv.custom) - s_editMode = 2; - else - s_editMode = 1; - break; - case EVT_KEY_LONG(KEY_ENTER): - if (s_editMode <= 0) { - if (int8_t(++m_posHorz) > 4) - m_posHorz = -4; - for (uint8_t i=0; i 0) { - if (--s_editMode == 0) - m_posHorz = 0; - } - else { - popMenu(); - } - break; - - /* CASE_EVT_ROTARY_LEFT */ - case EVT_KEY_REPT(KEY_LEFT): - case EVT_KEY_FIRST(KEY_LEFT): - if (s_editMode==1 && m_posHorz>0) m_posHorz--; - if (s_editMode <= 0) { - if (crv.custom) { - moveCurve(s_curveChan, -crv.points+2); - } - else if (crv.points > MIN_POINTS) { - moveCurve(s_curveChan, -1, (crv.points+1)/2); - } - else { - AUDIO_WARNING2(); - } - return; - } - break; - - /* CASE_EVT_ROTARY_RIGHT */ - case EVT_KEY_REPT(KEY_RIGHT): - case EVT_KEY_FIRST(KEY_RIGHT): - if (s_editMode==1 && m_posHorz<(crv.points-1)) m_posHorz++; - if (s_editMode <= 0) { - if (!crv.custom) { - moveCurve(s_curveChan, crv.points-2, crv.points); - } - else if (crv.points < MAX_POINTS) { - if (moveCurve(s_curveChan, 1)) { - for (int8_t i=crv.points+crv.points-2; i>=0; i--) { - if (i%2) - crv.crv[i] = (crv.crv[i/2] + crv.crv[1+i/2]) / 2; - else - crv.crv[i] = crv.crv[i/2]; - } - } - } - else { - AUDIO_WARNING2(); - } - } - break; - } - - lcd_putsLeft(7*FH, STR_TYPE); - uint8_t attr = (s_editMode <= 0 ? INVERS : 0); - lcd_outdezAtt(5*FW-2, 7*FH, crv.points, LEFT|attr); - lcd_putsAtt(lcdLastPos, 7*FH, crv.custom ? PSTR("pt'") : PSTR("pt"), attr); - - DrawCurve(); - - if (s_editMode>0) { - uint8_t i = m_posHorz; - point_t point = getPoint(i); - - if (s_editMode==1 || !BLINK_ON_PHASE) { - // do selection square - lcd_filled_rect(point.x-1, point.y-2, 5, 5, SOLID, FORCE); - lcd_filled_rect(point.x, point.y-1, 3, 3, SOLID); - } - - int8_t x = -100 + 200*i/(crv.points-1); - if (crv.custom && i>0 && i= 0 && sub < MAX_CURVES) - #define GVAR_SELECTED() (sub >= MAX_CURVES) -#else - #define CURVE_SELECTED() (sub >= 0) -#endif - -void menuModelCurvesAll(uint8_t event) -{ -#if defined(GVARS) && defined(PCBSTD) - SIMPLE_MENU(STR_MENUCURVES, menuTabModel, e_CurvesAll, 1+MAX_CURVES+MAX_GVARS); -#else - SIMPLE_MENU(STR_MENUCURVES, menuTabModel, e_CurvesAll, 1+MAX_CURVES); -#endif - - int8_t sub = m_posVert - 1; - - switch (event) { -#if defined(ROTARY_ENCODER_NAVIGATION) - case EVT_ROTARY_BREAK: -#endif -#if defined(PCBTARANIS) - case EVT_KEY_BREAK(KEY_ENTER): -#else - case EVT_KEY_FIRST(KEY_RIGHT): - case EVT_KEY_FIRST(KEY_ENTER): -#endif - if (CURVE_SELECTED() && !READ_ONLY()) { - s_curveChan = sub; - pushMenu(menuModelCurveOne); - } - break; - } - - for (uint8_t i=0; i= MAX_CURVES) { - putsStrIdx(0, y, STR_GV, k-MAX_CURVES+1); - if (GVAR_SELECTED()) { - if (attr && s_editMode>0) attr |= BLINK; - lcd_outdezAtt(10*FW, y, GVAR_VALUE(k-MAX_CURVES, -1), attr); - if (attr) g_model.gvars[k-MAX_CURVES] = checkIncDec(event, g_model.gvars[k-MAX_CURVES], -1000, 1000, EE_MODEL); - } - } - else -#endif - { - putsStrIdx(0, y, STR_CV, k+1, attr); -#if defined(PCBTARANIS) - editName(4*FW, y, g_model.curveNames[k], sizeof(g_model.curveNames[k]), 0, 0); - CurveInfo & crv = g_model.curves[k]; - lcd_outdezAtt(11*FW, y, 5+crv.points, LEFT); - lcd_putsAtt(lcdLastPos, y, STR_PTS, 0); -#endif - } - } - - if (CURVE_SELECTED()) { - s_curveChan = sub; - DrawCurve(23); - } -} -#endif - #if LCD_W >= 212 && defined(GVARS) && defined(FLIGHT_MODES) void onGVARSMenu(const char *result) diff --git a/radio/src/gui/menu_model_curves.cpp b/radio/src/gui/menu_model_curves.cpp new file mode 100755 index 000000000..0e8433939 --- /dev/null +++ b/radio/src/gui/menu_model_curves.cpp @@ -0,0 +1,514 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../opentx.h" + +uint8_t s_curveChan; + +int16_t curveFn(int16_t x) +{ + return applyCustomCurve(x, s_curveChan); +} + +struct point_t { + coord_t x; + coord_t y; +}; + +point_t getPoint(uint8_t i) +{ + point_t result = {0, 0}; +#if defined(PCBTARANIS) + CurveInfo &crv = g_model.curves[s_curveChan]; + int8_t *points = curveAddress(s_curveChan); + bool custom = (crv.type == CURVE_TYPE_CUSTOM); + uint8_t count = 5+crv.points; +#else + CurveInfo crv = curveInfo(s_curveChan); + int8_t *points = crv.crv; + bool custom = crv.custom; + uint8_t count = crv.points; +#endif + if (i < count) { +#if defined(PCBTARANIS) + result.x = X0-1-WCHART+i*WCHART*2/(count-1); +#else + result.x = X0-1-WCHART+i*WCHART/(count/2); +#endif + result.y = (LCD_H-1) - (100 + points[i]) * (LCD_H-1) / 200; + if (custom && i>0 && i g_model.points + sizeof(g_model.points)) { + AUDIO_WARNING2(); + return false; + } + + int8_t *nextCrv = curveAddress(index+1); + memmove(nextCrv+shift, nextCrv, 5*(MAX_CURVES-index-1)+curveEnd[MAX_CURVES-1]-curveEnd[index]); + if (shift < 0) memclear(&g_model.points[NUM_POINTS-1] + shift, -shift); + while (index NUM_POINTS-5*MAX_CURVES) { + AUDIO_WARNING2(); + return false; + } + + int8_t *crv = curveAddress(index); + if (shift < 0) { + for (uint8_t i=0; i0 ? INVERS|BLINK : INVERS) : 0); + lcd_putsLeft(3*FH+1, STR_TYPE); + lcd_putsiAtt(INDENT_WIDTH, 4*FH+1, STR_CURVE_TYPES, crv.type, attr); + if (attr) { + uint8_t newType = checkIncDecModelZero(event, crv.type, CURVE_TYPE_LAST); + if (newType != crv.type) { + for (int i=1; i<4+crv.points; i++) + points[i] = calcRESXto100(applyCustomCurve(calc100toRESX(-100 + i*200/(4+crv.points)), s_curveChan)); + moveCurve(s_curveChan, checkIncDec_Ret > 0 ? 3+crv.points : -3-crv.points); + if (newType == CURVE_TYPE_CUSTOM) { + for (int i=0; i<3+crv.points; i++) + points[5+crv.points+i] = -100 + ((i+1)*200) / (4+crv.points); + } + crv.type = newType; + } + } + + attr = (m_posVert==2 ? (s_editMode>0 ? INVERS|BLINK : INVERS) : 0); + lcd_putsLeft(5*FH+1, STR_COUNT); + lcd_outdezAtt(INDENT_WIDTH, 6*FH+1, 5+crv.points, LEFT|attr); + lcd_putsAtt(lcdLastPos, 6*FH+1, STR_PTS, attr); + if (attr) { + int8_t count = checkIncDecModel(event, crv.points, -3, 12); // 2pts - 17pts + if (checkIncDec_Ret) { + int8_t newPoints[MAX_POINTS]; + newPoints[0] = points[0]; + newPoints[4+count] = points[4+crv.points]; + for (int i=1; i<4+count; i++) + newPoints[i] = calcRESXto100(applyCustomCurve(calc100toRESX(-100 + (i*200) / (4+count)), s_curveChan)); + moveCurve(s_curveChan, checkIncDec_Ret*(crv.type==CURVE_TYPE_CUSTOM?2:1)); + for (int i=0; i<5+count; i++) { + points[i] = newPoints[i]; + if (crv.type == CURVE_TYPE_CUSTOM && i!=0 && i!=4+count) + points[5+count+i-1] = -100 + (i*200) / (4+count); + } + crv.points = count; + } + } + + lcd_putsLeft(7*FH+1, STR_SMOOTH); + menu_lcd_onoff(7*FW, 7*FH+1, crv.smooth, m_posVert==3 ? INVERS : 0); + if (m_posVert==3) crv.smooth = checkIncDecModel(event, crv.smooth, 0, 1); + + switch(event) { + case EVT_ENTRY: + pointsOfs = 0; + SET_SCROLLBAR_X(0); + break; + case EVT_KEY_LONG(KEY_ENTER): + if (m_posVert > 1) { + killEvents(event); + MENU_ADD_ITEM(STR_CURVE_PRESET); + MENU_ADD_ITEM(STR_MIRROR); + MENU_ADD_ITEM(STR_CLEAR); + menuHandler = onCurveOneMenu; + } + break; + case EVT_KEY_LONG(KEY_MENU): + pushMenu(menuChannelsView); + killEvents(event); + } + + DrawCurve(FW); + + uint8_t posY = FH+1; + attr = (s_editMode > 0 ? INVERS|BLINK : INVERS); + for (uint8_t i=0; i<5+crv.points; i++) { + point_t point = getPoint(i); + uint8_t selectionMode = 0; + if (crv.type==CURVE_TYPE_CUSTOM) { + if (m_posVert==4+2*i || (i==5+crv.points-1 && m_posVert==4+5+crv.points+5+crv.points-2-1)) + selectionMode = 2; + else if (i>0 && m_posVert==3+2*i) + selectionMode = 1; + } + else if (m_posVert == 4+i) { + selectionMode = 2; + } + + if (i>=pointsOfs && i0 && i<5+crv.points-1) x = points[5+crv.points+i-1]; + lcd_outdezAtt(6+8*FW, posY, i+1, LEFT); + lcd_outdezAtt(3+12*FW, posY, x, LEFT|(selectionMode==1?attr:0)); + lcd_outdezAtt(3+16*FW, posY, points[i], LEFT|(selectionMode==2?attr:0)); + posY += FH; + } + + if (selectionMode > 0) { + // do selection square + lcd_filled_rect(point.x-FW-1, point.y-2, 5, 5, SOLID, FORCE); + lcd_filled_rect(point.x-FW, point.y-1, 3, 3, SOLID); + if (s_editMode > 0) { + if (selectionMode == 1) + CHECK_INCDEC_MODELVAR(event, points[5+crv.points+i-1], i==1 ? -100 : points[5+crv.points+i-2], i==5+crv.points-2 ? 100 : points[5+crv.points+i]); // edit X + else if (selectionMode == 2) + CHECK_INCDEC_MODELVAR(event, points[i], -100, 100); + } + if (i < pointsOfs) + pointsOfs = i; + else if (i > pointsOfs+6) + pointsOfs = i-6; + } + } +} +#else +void menuModelCurveOne(uint8_t event) +{ + TITLE(STR_MENUCURVE); + lcd_outdezAtt(PSIZE(TR_MENUCURVE)*FW+1, 0, s_curveChan+1, INVERS|LEFT); + DISPLAY_PROGRESS_BAR(20*FW+1); + + CurveInfo crv = curveInfo(s_curveChan); + + switch(event) { + case EVT_ENTRY: + s_editMode = 1; + break; + CASE_EVT_ROTARY_BREAK + case EVT_KEY_BREAK(KEY_ENTER): + if (s_editMode <= 0) + m_posHorz = 0; + if (s_editMode == 1 && crv.custom) + s_editMode = 2; + else + s_editMode = 1; + break; + case EVT_KEY_LONG(KEY_ENTER): + if (s_editMode <= 0) { + if (int8_t(++m_posHorz) > 4) + m_posHorz = -4; + for (uint8_t i=0; i 0) { + if (--s_editMode == 0) + m_posHorz = 0; + } + else { + popMenu(); + } + break; + + /* CASE_EVT_ROTARY_LEFT */ + case EVT_KEY_REPT(KEY_LEFT): + case EVT_KEY_FIRST(KEY_LEFT): + if (s_editMode==1 && m_posHorz>0) m_posHorz--; + if (s_editMode <= 0) { + if (crv.custom) { + moveCurve(s_curveChan, -crv.points+2); + } + else if (crv.points > MIN_POINTS) { + moveCurve(s_curveChan, -1, (crv.points+1)/2); + } + else { + AUDIO_WARNING2(); + } + return; + } + break; + + /* CASE_EVT_ROTARY_RIGHT */ + case EVT_KEY_REPT(KEY_RIGHT): + case EVT_KEY_FIRST(KEY_RIGHT): + if (s_editMode==1 && m_posHorz<(crv.points-1)) m_posHorz++; + if (s_editMode <= 0) { + if (!crv.custom) { + moveCurve(s_curveChan, crv.points-2, crv.points); + } + else if (crv.points < MAX_POINTS) { + if (moveCurve(s_curveChan, 1)) { + for (int8_t i=crv.points+crv.points-2; i>=0; i--) { + if (i%2) + crv.crv[i] = (crv.crv[i/2] + crv.crv[1+i/2]) / 2; + else + crv.crv[i] = crv.crv[i/2]; + } + } + } + else { + AUDIO_WARNING2(); + } + } + break; + } + + lcd_putsLeft(7*FH, STR_TYPE); + uint8_t attr = (s_editMode <= 0 ? INVERS : 0); + lcd_outdezAtt(5*FW-2, 7*FH, crv.points, LEFT|attr); + lcd_putsAtt(lcdLastPos, 7*FH, crv.custom ? PSTR("pt'") : PSTR("pt"), attr); + + DrawCurve(); + + if (s_editMode>0) { + uint8_t i = m_posHorz; + point_t point = getPoint(i); + + if (s_editMode==1 || !BLINK_ON_PHASE) { + // do selection square + lcd_filled_rect(point.x-1, point.y-2, 5, 5, SOLID, FORCE); + lcd_filled_rect(point.x, point.y-1, 3, 3, SOLID); + } + + int8_t x = -100 + 200*i/(crv.points-1); + if (crv.custom && i>0 && i= 0 && sub < MAX_CURVES) + #define GVAR_SELECTED() (sub >= MAX_CURVES) +#else + #define CURVE_SELECTED() (sub >= 0) +#endif + +void menuModelCurvesAll(uint8_t event) +{ +#if defined(GVARS) && defined(PCBSTD) + SIMPLE_MENU(STR_MENUCURVES, menuTabModel, e_CurvesAll, 1+MAX_CURVES+MAX_GVARS); +#else + SIMPLE_MENU(STR_MENUCURVES, menuTabModel, e_CurvesAll, 1+MAX_CURVES); +#endif + + int8_t sub = m_posVert - 1; + + switch (event) { +#if defined(ROTARY_ENCODER_NAVIGATION) + case EVT_ROTARY_BREAK: +#endif +#if defined(PCBTARANIS) + case EVT_KEY_BREAK(KEY_ENTER): +#else + case EVT_KEY_FIRST(KEY_RIGHT): + case EVT_KEY_FIRST(KEY_ENTER): +#endif + if (CURVE_SELECTED() && !READ_ONLY()) { + s_curveChan = sub; + pushMenu(menuModelCurveOne); + } + break; + } + + for (uint8_t i=0; i= MAX_CURVES) { + putsStrIdx(0, y, STR_GV, k-MAX_CURVES+1); + if (GVAR_SELECTED()) { + if (attr && s_editMode>0) attr |= BLINK; + lcd_outdezAtt(10*FW, y, GVAR_VALUE(k-MAX_CURVES, -1), attr); + if (attr) g_model.gvars[k-MAX_CURVES] = checkIncDec(event, g_model.gvars[k-MAX_CURVES], -1000, 1000, EE_MODEL); + } + } + else +#endif + { + putsStrIdx(0, y, STR_CV, k+1, attr); +#if defined(PCBTARANIS) + editName(4*FW, y, g_model.curveNames[k], sizeof(g_model.curveNames[k]), 0, 0); + CurveInfo & crv = g_model.curves[k]; + lcd_outdezAtt(11*FW, y, 5+crv.points, LEFT); + lcd_putsAtt(lcdLastPos, y, STR_PTS, 0); +#endif + } + } + + if (CURVE_SELECTED()) { + s_curveChan = sub; + DrawCurve(23); + } +}