void menuMainView(uint8_t event) { STICK_SCROLL_DISABLE(); uint8_t view = g_eeGeneral.view; uint8_t view_base = view & 0x0f; switch(event) { case EVT_ENTRY: killEvents(KEY_EXIT); killEvents(KEY_UP); killEvents(KEY_DOWN); break; /* TODO if timer2 is OFF, it's possible to use this timer2 as in er9x... case EVT_KEY_BREAK(KEY_MENU): if (view_base == VIEW_TIMER2) { Timer2_running = !Timer2_running; AUDIO_KEYPAD_UP(); } break; */ case EVT_KEY_BREAK(KEY_RIGHT): case EVT_KEY_BREAK(KEY_LEFT): if (view_base <= VIEW_INPUTS) { #if defined(PCBSKY9X) if (view_base == VIEW_INPUTS) g_eeGeneral.view ^= ALTERNATE_VIEW; else g_eeGeneral.view = (g_eeGeneral.view + (4*ALTERNATE_VIEW) + ((event==EVT_KEY_BREAK(KEY_LEFT)) ? -ALTERNATE_VIEW : ALTERNATE_VIEW)) % (4*ALTERNATE_VIEW); #else g_eeGeneral.view ^= ALTERNATE_VIEW; #endif eeDirty(EE_GENERAL); AUDIO_KEYPAD_UP(); } break; #if defined(NAVIGATION_MENUS) case EVT_KEY_CONTEXT_MENU: killEvents(event); #if defined(CPUARM) if (modelHasNotes()) { MENU_ADD_ITEM(STR_VIEW_NOTES); } #endif #if defined(CPUARM) MENU_ADD_ITEM(STR_RESET_SUBMENU); #else MENU_ADD_ITEM(STR_RESET_TIMER1); MENU_ADD_ITEM(STR_RESET_TIMER2); #if defined(FRSKY) MENU_ADD_ITEM(STR_RESET_TELEMETRY); #endif MENU_ADD_ITEM(STR_RESET_FLIGHT); #endif MENU_ADD_ITEM(STR_STATISTICS); #if defined(CPUARM) MENU_ADD_ITEM(STR_ABOUT_US); #endif menuHandler = onMainViewMenu; break; #endif #if MENUS_LOCK != 2 /*no menus*/ case EVT_KEY_LONG(KEY_MENU):// go to last menu pushMenu(lastPopMenu()); killEvents(event); break; CASE_EVT_ROTARY_BREAK case EVT_KEY_MODEL_MENU: pushMenu(menuModelSelect); killEvents(event); break; CASE_EVT_ROTARY_LONG case EVT_KEY_GENERAL_MENU: pushMenu(menuGeneralSetup); killEvents(event); break; #endif case EVT_KEY_BREAK(KEY_UP): case EVT_KEY_BREAK(KEY_DOWN): g_eeGeneral.view = (event == EVT_KEY_BREAK(KEY_UP) ? (view_base == VIEW_COUNT-1 ? 0 : view_base+1) : (view_base == 0 ? VIEW_COUNT-1 : view_base-1)); eeDirty(EE_GENERAL); AUDIO_KEYPAD_UP(); break; case EVT_KEY_STATISTICS: chainMenu(menuStatisticsView); killEvents(event); break; case EVT_KEY_TELEMETRY: #if defined(FRSKY) if (!IS_FAI_ENABLED()) chainMenu(menuTelemetryFrsky); #elif defined(JETI) JETI_EnableRXD(); // enable JETI-Telemetry reception chainMenu(menuTelemetryJeti); #elif defined(ARDUPILOT) ARDUPILOT_EnableRXD(); // enable ArduPilot-Telemetry reception chainMenu(menuTelemetryArduPilot); #elif defined(NMEA) NMEA_EnableRXD(); // enable NMEA-Telemetry reception chainMenu(menuTelemetryNMEA); #elif defined(MAVLINK) chainMenu(menuTelemetryMavlink); #else chainMenu(menuStatisticsDebug); #endif killEvents(event); break; case EVT_KEY_FIRST(KEY_EXIT): #if defined(GVARS) && !defined(PCBSTD) if (s_gvar_timer > 0) { s_gvar_timer = 0; } #endif if (view == VIEW_TIMER2) { timerReset(1); } AUDIO_KEYPAD_UP(); break; #if !defined(NAVIGATION_MENUS) case EVT_KEY_LONG(KEY_EXIT): flightReset(); AUDIO_KEYPAD_UP(); break; #endif } { // Flight Mode Name uint8_t mode = mixerCurrentFlightMode; lcd_putsnAtt(PHASE_X, PHASE_Y, g_model.flightModeData[mode].name, sizeof(g_model.flightModeData[mode].name), ZCHAR|PHASE_FLAGS); // Model Name putsModelName(MODELNAME_X, MODELNAME_Y, g_model.header.name, g_eeGeneral.currModel, BIGSIZE); // Main Voltage (or alarm if any) displayVoltageOrAlarm(); // Timers displayTimers(); // Trims sliders displayTrims(mode); } if (view_base < VIEW_INPUTS) { // scroll bar lcd_hlineStip(38, 34, 54, DOTTED); #if defined(PCBSKY9X) lcd_hline(38 + (g_eeGeneral.view / ALTERNATE_VIEW) * 13, 34, 13, SOLID); #else lcd_hline((g_eeGeneral.view & ALTERNATE_VIEW) ? 64 : 38, 34, 26, SOLID); #endif for (uint8_t i=0; i<8; i++) { uint8_t x0,y0; #if defined(PCBSKY9X) uint8_t chan = 8*(g_eeGeneral.view / ALTERNATE_VIEW) + i; #else uint8_t chan = (g_eeGeneral.view & ALTERNATE_VIEW) ? 8+i : i; #endif int16_t val = channelOutputs[chan]; switch(view_base) { case VIEW_OUTPUTS_VALUES: x0 = (i%4*9+3)*FW/2; y0 = i/4*FH+40; #if defined(PPM_UNIT_US) lcd_outdezAtt(x0+4*FW , y0, PPM_CH_CENTER(chan)+val/2, 0); #elif defined(PPM_UNIT_PERCENT_PREC1) lcd_outdezAtt(x0+4*FW , y0, calcRESXto1000(val), PREC1); #else lcd_outdezAtt(x0+4*FW , y0, calcRESXto1000(val)/10, 0); // G: Don't like the decimal part* #endif break; case VIEW_OUTPUTS_BARS: #define WBAR2 (50/2) x0 = i<4 ? LCD_W/4+2 : LCD_W*3/4-2; y0 = 38+(i%4)*5; uint16_t lim = g_model.extendedLimits ? 640*2 : 512*2; int8_t len = (abs(val) * WBAR2 + lim/2) / lim; if(len>WBAR2) len = WBAR2; // prevent bars from going over the end - comment for debugging lcd_hlineStip(x0-WBAR2, y0, WBAR2*2+1, DOTTED); lcd_vline(x0,y0-2,5); if (val>0) x0+=1; else x0-=len; lcd_hline(x0,y0+1,len); lcd_hline(x0,y0-1,len); break; } } } else if (view_base == VIEW_INPUTS) { if (view == VIEW_INPUTS) { // Sticks + Pots doMainScreenGraphics(); // Switches for (uint8_t i=SWSRC_THR; i<=SWSRC_TRN; i++) { int8_t sw = (i == SWSRC_TRN ? (switchState(SW_ID0) ? SWSRC_ID0 : (switchState(SW_ID1) ? SWSRC_ID1 : SWSRC_ID2)) : i); uint8_t x = 2*FW-2, y = i*FH+1; if (i>=SWSRC_AIL) { x = 17*FW-1; y -= 3*FH; } putsSwitches(x, y, sw, getSwitch(i) ? INVERS : 0); } } else { #if defined(PCBMEGA2560) && defined(ROTARY_ENCODERS) for (uint8_t i=0; i<NUM_ROTARY_ENCODERS; i++) { int16_t val = getRotaryEncoder(i); int8_t len = limit((int16_t)0, (int16_t)(((val+1024) * BAR_HEIGHT) / 2048), (int16_t)BAR_HEIGHT); #if ROTARY_ENCODERS > 2 #define V_BAR_W 5 V_BAR(LCD_W/2-8+V_BAR_W*i, LCD_H-8, len); #else #define V_BAR_W 5 V_BAR(LCD_W/2-3+V_BAR_W*i, LCD_H-8, len); #endif } #endif // PCBGRUVIN9X && ROTARY_ENCODERS // Logical Switches #if defined(PCBSKY9X) for (uint8_t i=0; i<NUM_LOGICAL_SWITCH; i++) { int8_t len = getSwitch(SWSRC_SW1+i) ? BAR_HEIGHT : 1; uint8_t x = VSWITCH_X(i); lcd_vline(x-1, VSWITCH_Y-len, len); lcd_vline(x, VSWITCH_Y-len, len); } #elif defined(CPUM2560) for (uint8_t i=0; i<NUM_LOGICAL_SWITCH; i++) putsSwitches(2*FW-3 + (i/3)*(i/3>2 ? 3*FW+2 : (3*FW-1)) + (i/3>2 ? 2*FW : 0), 4*FH+1 + (i%3)*FH, SWSRC_SW1+i, getSwitch(SWSRC_SW1+i) ? INVERS : 0); #elif !defined(PCBSTD) for (uint8_t i=0; i<NUM_LOGICAL_SWITCH; i++) putsSwitches(2*FW-2 + (i/3)*(4*FW-1), 4*FH+1 + (i%3)*FH, SWSRC_SW1+i, getSwitch(SWSRC_SW1+i) ? INVERS : 0); #else for (uint8_t i=0; i<NUM_LOGICAL_SWITCH; i++) putsSwitches(2*FW-3 + (i/3)*(4*FW), 4*FH+1 + (i%3)*FH, SWSRC_SW1+i, getSwitch(SWSRC_SW1+i) ? INVERS : 0); #endif } } else { // timer2 #if defined(TRANSLATIONS_CZ) #define TMR2_LBL_COL (20-FW/2+1) #else #define TMR2_LBL_COL (20-FW/2+5) #endif putsTimer(33+FW+2+10*FWNUM-4, FH*5, timersStates[1].val, DBLSIZE, DBLSIZE); putsTimerMode(timersStates[1].val >= 0 ? TMR2_LBL_COL : TMR2_LBL_COL-7, FH*6, g_model.timers[1].mode); // lcd_outdezNAtt(33+11*FW, FH*6, s_timerVal_10ms[1], LEADING0, 2); // 1/100s } // And ! in case of unexpected shutdown if (unexpectedShutdown) { lcd_putcAtt(REBOOT_X, 0*FH, '!', INVERS); } #if defined(GVARS) && !defined(PCBSTD) if (s_gvar_timer > 0) { s_gvar_timer--; s_warning = STR_GLOBAL_VAR; displayBox(); lcd_putsnAtt(16, 5*FH, g_model.gvars[s_gvar_last].name, LEN_GVAR_NAME, ZCHAR); lcd_putsAtt(16+7*FW, 5*FH, PSTR("[\010]"), BOLD); lcd_outdezAtt(16+7*FW+4*FW+FW/2, 5*FH, GVAR_VALUE(s_gvar_last, getGVarFlightPhase(mixerCurrentFlightMode, s_gvar_last)), BOLD); s_warning = NULL; } #endif #if defined(DSM2) if (moduleFlag[0] == MODULE_BIND) { // Issue 98 lcd_putsAtt(15*FW, 0, PSTR("BIND"), 0); } #endif }
void menuModelLimits(uint8_t event) { int sub = menuVerticalPosition; if (sub < NUM_CHNOUT) { #if defined(PPM_CENTER_ADJUSTABLE) || defined(PPM_UNIT_US) lcd_outdezAtt(13*FW, 0, PPM_CH_CENTER(sub)+channelOutputs[sub]/2, 0); lcd_puts(13*FW, 0, STR_US); #else lcd_outdezAtt(13*FW, 0, calcRESXto1000(channelOutputs[sub]), PREC1); #endif } MENU(STR_MENULIMITS, menuTabModel, e_Limits, NUM_CHNOUT+1, { NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, 0 }); if (sub<NUM_CHNOUT && menuHorizontalPosition>=0) { displayColumnHeader(STR_LIMITS_HEADERS, menuHorizontalPosition); } if (warningResult) { warningResult = 0; LimitData *ld = limitAddress(sub); ld->revert = !ld->revert; eeDirty(EE_MODEL); } for (int i=0; i<NUM_BODY_LINES; i++) { coord_t y = MENU_HEADER_HEIGHT + 1 + i*FH; uint8_t k = i+menuVerticalOffset; if (k==NUM_CHNOUT) { // last line available - add the "copy trim menu" line uint8_t attr = (sub==NUM_CHNOUT) ? INVERS : 0; lcd_putsAtt(CENTER_OFS, y, STR_TRIMS2OFFSETS, NO_HIGHLIGHT() ? 0 : attr); if (attr) { s_editMode = 0; if (event==EVT_KEY_LONG(KEY_ENTER)) { START_NO_HIGHLIGHT(); killEvents(event); moveTrimsToOffsets(); // if highlighted and menu pressed - move trims to offsets } } return; } LimitData *ld = limitAddress(k); int16_t v = (ld->revert) ? -LIMIT_OFS(ld) : LIMIT_OFS(ld); char swVal = '-'; // '-', '<', '>' if ((channelOutputs[k] - v) > 50) swVal = (ld->revert ? 127 : 126); // Switch to raw inputs? - remove trim! if ((channelOutputs[k] - v) < -50) swVal = (ld->revert ? 126 : 127); lcd_putc(LIMITS_DIRECTION_POS, y, swVal); int limit = (g_model.extendedLimits ? LIMIT_EXT_MAX : 1000); putsChn(0, y, k+1, (sub==k && menuHorizontalPosition < 0) ? INVERS : 0); if (sub==k && menuHorizontalPosition < 0 && event==EVT_KEY_LONG(KEY_ENTER) && !READ_ONLY()) { killEvents(event); POPUP_MENU_ADD_ITEM(STR_RESET); POPUP_MENU_ADD_ITEM(STR_COPY_TRIMS_TO_OFS); POPUP_MENU_ADD_ITEM(STR_COPY_STICKS_TO_OFS); popupMenuHandler = onLimitsMenu; } for (int j=0; j<ITEM_LIMITS_COUNT; j++) { LcdFlags attr = ((sub==k && menuHorizontalPosition==j) ? ((s_editMode>0) ? BLINK|INVERS : INVERS) : 0); uint8_t active = (attr && s_editMode>0) ; if (active) STICK_SCROLL_DISABLE(); switch(j) { case ITEM_LIMITS_CH_NAME: editName(LIMITS_NAME_POS, y, ld->name, sizeof(ld->name), event, attr); break; case ITEM_LIMITS_OFFSET: if (GV_IS_GV_VALUE(ld->offset, -1000, 1000) || (attr && event == EVT_KEY_LONG(KEY_ENTER))) { ld->offset = GVAR_MENU_ITEM(LIMITS_OFFSET_POS, y, ld->offset, -1000, 1000, attr|PREC1, 0, event); break; } #if defined(PPM_UNIT_US) lcd_outdezAtt(LIMITS_OFFSET_POS, y, ((int32_t)ld->offset*128) / 25, attr|PREC1); #else lcd_outdezAtt(LIMITS_OFFSET_POS, y, ld->offset, attr|PREC1); #endif if (active) { ld->offset = checkIncDec(event, ld->offset, -1000, 1000, EE_MODEL, NULL, stops1000); } else if (attr && event==EVT_KEY_LONG(KEY_MENU)) { copySticksToOffset(k); s_editMode = 0; } break; case ITEM_LIMITS_MIN: if (GV_IS_GV_VALUE(ld->min, -GV_RANGELARGE, GV_RANGELARGE) || (attr && event == EVT_KEY_LONG(KEY_ENTER))) { ld->min = GVAR_MENU_ITEM(LIMITS_MIN_POS, y, ld->min, -LIMIT_EXT_MAX, LIMIT_EXT_MAX, MIN_MAX_ATTR, 0, event); break; } lcd_outdezAtt(LIMITS_MIN_POS, y, MIN_MAX_DISPLAY(ld->min-LIMITS_MIN_MAX_OFFSET), MIN_MAX_ATTR); if (active) ld->min = LIMITS_MIN_MAX_OFFSET + checkIncDec(event, ld->min-LIMITS_MIN_MAX_OFFSET, -limit, 0, EE_MODEL, NULL, stops1000); break; case ITEM_LIMITS_MAX: if (GV_IS_GV_VALUE(ld->max, -GV_RANGELARGE, GV_RANGELARGE) || (attr && event == EVT_KEY_LONG(KEY_ENTER))) { ld->max = GVAR_MENU_ITEM(LIMITS_MAX_POS, y, ld->max, -LIMIT_EXT_MAX, LIMIT_EXT_MAX, MIN_MAX_ATTR, 0, event); break; } lcd_outdezAtt(LIMITS_MAX_POS, y, MIN_MAX_DISPLAY(ld->max+LIMITS_MIN_MAX_OFFSET), MIN_MAX_ATTR); if (active) ld->max = -LIMITS_MIN_MAX_OFFSET + checkIncDec(event, ld->max+LIMITS_MIN_MAX_OFFSET, 0, +limit, EE_MODEL, NULL, stops1000); break; case ITEM_LIMITS_DIRECTION: { uint8_t revert = ld->revert; #if defined(PPM_CENTER_ADJUSTABLE) lcd_putcAtt(LIMITS_REVERT_POS, y, revert ? 127 : 126, attr); #else lcd_putsiAtt(LIMITS_REVERT_POS, y, STR_MMMINV, revert, attr); #endif if (active) { uint8_t revert_new = checkIncDecModel(event, revert, 0, 1); if (checkIncDec_Ret && isThrottleOutput(k)) { POPUP_CONFIRMATION(STR_INVERT_THR); } else { ld->revert = revert_new; } } break; } #if defined(CURVES) case ITEM_LIMITS_CURVE: putsCurve(LIMITS_CURVE_POS, y, ld->curve, attr); if (attr && event==EVT_KEY_LONG(KEY_ENTER) && ld->curve>0) { s_curveChan = (ld->curve<0 ? -ld->curve-1 : ld->curve-1); pushMenu(menuModelCurveOne); } if (active) { CHECK_INCDEC_MODELVAR(event, ld->curve, -MAX_CURVES, +MAX_CURVES); } break; #endif #if defined(PPM_CENTER_ADJUSTABLE) case ITEM_LIMITS_PPM_CENTER: lcd_outdezAtt(LIMITS_PPM_CENTER_POS, y, PPM_CENTER+ld->ppmCenter, attr); if (active) { CHECK_INCDEC_MODELVAR(event, ld->ppmCenter, -PPM_CENTER_MAX, +PPM_CENTER_MAX); } break; #endif #if defined(PPM_LIMITS_SYMETRICAL) case ITEM_LIMITS_SYMETRICAL: lcd_putcAtt(LCD_W-FW-MENUS_SCROLLBAR_WIDTH, y, ld->symetrical ? '=' : '\306', attr); if (active) { CHECK_INCDEC_MODELVAR_ZERO(event, ld->symetrical, 1); } break; #endif } } } }
void menuModelFailsafe(uint8_t event) { static bool longNames = false; bool newLongNames = false; uint8_t ch = 0; uint8_t channelStart = g_model.moduleData[g_moduleIdx].channelsStart; if (event == EVT_KEY_LONG(KEY_ENTER)) { killEvents(event); event = 0; if (s_editMode) { g_model.moduleData[g_moduleIdx].failsafeChannels[menuVerticalPosition] = channelOutputs[menuVerticalPosition+channelStart]; eeDirty(EE_MODEL); AUDIO_WARNING1(); s_editMode = 0; SEND_FAILSAFE_NOW(g_moduleIdx); } else { int16_t & failsafe = g_model.moduleData[g_moduleIdx].failsafeChannels[menuVerticalPosition]; if (failsafe < FAILSAFE_CHANNEL_HOLD) failsafe = FAILSAFE_CHANNEL_HOLD; else if (failsafe == FAILSAFE_CHANNEL_HOLD) failsafe = FAILSAFE_CHANNEL_NOPULSE; else failsafe = 0; eeDirty(EE_MODEL); AUDIO_WARNING1(); SEND_FAILSAFE_NOW(g_moduleIdx); } } SIMPLE_SUBMENU_NOTITLE(NUM_CHANNELS(g_moduleIdx)); SET_SCROLLBAR_X(0); #define COL_W (LCD_W/2) const uint8_t SLIDER_W = 64; // Column separator lcd_vline(LCD_W/2, FH, LCD_H-FH); lcd_putsCenter(0*FH, FAILSAFESET); lcd_invert_line(0); unsigned int lim = g_model.extendedLimits ? 640*2 : 512*2; for (uint8_t col=0; col<2; col++) { coord_t x = col*COL_W+1; // Channels for (uint8_t line=0; line<8; line++) { coord_t y = 9+line*7; int32_t channelValue = channelOutputs[ch+channelStart]; int32_t failsafeValue = 0; bool failsafeEditable = false; uint8_t ofs = (col ? 0 : 1); if (ch < NUM_CHANNELS(g_moduleIdx)) { failsafeValue = g_model.moduleData[g_moduleIdx].failsafeChannels[8*col+line]; failsafeEditable = true; } if (failsafeEditable) { // Channel name if present, number if not uint8_t lenLabel = ZLEN(g_model.limitData[ch+channelStart].name); if (lenLabel > 4) { newLongNames = longNames = true; } if (lenLabel > 0) lcd_putsnAtt(x+1-ofs, y, g_model.limitData[ch+channelStart].name, sizeof(g_model.limitData[ch+channelStart].name), ZCHAR | SMLSIZE); else putsChn(x+1-ofs, y, ch+1, SMLSIZE); // Value LcdFlags flags = TINSIZE; if (menuVerticalPosition == ch) { flags |= INVERS; if (s_editMode) { if (failsafeValue == FAILSAFE_CHANNEL_HOLD || failsafeValue == FAILSAFE_CHANNEL_NOPULSE) { s_editMode = 0; } else { flags |= BLINK; CHECK_INCDEC_MODELVAR(event, g_model.moduleData[g_moduleIdx].failsafeChannels[8*col+line], -lim, +lim); } } } #if defined(PPM_UNIT_PERCENT_PREC1) uint8_t wbar = (longNames ? SLIDER_W-16 : SLIDER_W-6); #else uint8_t wbar = (longNames ? SLIDER_W-10 : SLIDER_W); #endif if (failsafeValue == FAILSAFE_CHANNEL_HOLD) { lcd_putsAtt(x+COL_W-4-wbar-ofs-16, y, "HOLD", flags); failsafeValue = 0; } else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) { lcd_putsAtt(x+COL_W-4-wbar-ofs-16, y, "NONE", flags); failsafeValue = 0; } else { #if defined(PPM_UNIT_US) lcd_outdezAtt(x+COL_W-4-wbar-ofs, y, PPM_CH_CENTER(ch)+failsafeValue/2, flags); #elif defined(PPM_UNIT_PERCENT_PREC1) lcd_outdezAtt(x+COL_W-4-wbar-ofs, y, calcRESXto1000(failsafeValue), PREC1|flags); #else lcd_outdezAtt(x+COL_W-4-wbar-ofs, y, calcRESXto1000(failsafeValue)/10, flags); #endif } // Gauge lcd_rect(x+COL_W-3-wbar-ofs, y, wbar+1, 6); unsigned int lenChannel = limit((uint8_t)1, uint8_t((abs(channelValue) * wbar/2 + lim/2) / lim), uint8_t(wbar/2)); unsigned int lenFailsafe = limit((uint8_t)1, uint8_t((abs(failsafeValue) * wbar/2 + lim/2) / lim), uint8_t(wbar/2)); coord_t xChannel = (channelValue>0) ? x+COL_W-ofs-3-wbar/2 : x+COL_W-ofs-2-wbar/2-lenChannel; coord_t xFailsafe = (failsafeValue>0) ? x+COL_W-ofs-3-wbar/2 : x+COL_W-ofs-2-wbar/2-lenFailsafe; lcd_hlineStip(xChannel, y+1, lenChannel, DOTTED, 0); lcd_hlineStip(xChannel, y+2, lenChannel, DOTTED, 0); lcd_hline(xFailsafe, y+3, lenFailsafe); lcd_hline(xFailsafe, y+4, lenFailsafe); } ch++; } } longNames = newLongNames; }
void menuModelExpoMix(uint8_t expo, uint8_t event) { uint8_t sub = m_posVert; if (s_editMode > 0) s_editMode = 0; uint8_t chn = (expo ? expoAddress(s_currIdx)->chn+1 : mixAddress(s_currIdx)->destCh+1); switch (event) { case EVT_ENTRY: case EVT_ENTRY_UP: s_copyMode = 0; s_copyTgtOfs = 0; break; case EVT_KEY_LONG(KEY_EXIT): if (s_copyMode && s_copyTgtOfs == 0) { deleteExpoMix(expo, s_currIdx); killEvents(event); event = 0; } // no break case EVT_KEY_BREAK(KEY_EXIT): if (s_copyMode) { if (s_copyTgtOfs) { // cancel the current copy / move operation if (s_copyMode == COPY_MODE) { deleteExpoMix(expo, s_currIdx); } else { do { swapExpoMix(expo, s_currIdx, s_copyTgtOfs > 0); s_copyTgtOfs += (s_copyTgtOfs < 0 ? +1 : -1); } while (s_copyTgtOfs != 0); eeDirty(EE_MODEL); } m_posVert = s_copySrcRow; s_copyTgtOfs = 0; } s_copyMode = 0; event = 0; } break; case EVT_KEY_BREAK(KEY_ENTER): if ((!s_currCh || (s_copyMode && !s_copyTgtOfs)) && !READ_ONLY()) { s_copyMode = (s_copyMode == COPY_MODE ? MOVE_MODE : COPY_MODE); s_copySrcIdx = s_currIdx; s_copySrcCh = chn; s_copySrcRow = sub; break; } // no break case EVT_KEY_LONG(KEY_ENTER): killEvents(event); if (s_copyTgtOfs) { s_copyMode = 0; s_copyTgtOfs = 0; } else { if (READ_ONLY()) { if (!s_currCh) { pushMenu(expo ? menuModelExpoOne : menuModelMixOne); } } else { if (s_copyMode) s_currCh = 0; if (s_currCh) { if (reachExpoMixCountLimit(expo)) break; insertExpoMix(expo, s_currIdx); pushMenu(expo ? menuModelExpoOne : menuModelMixOne); s_copyMode = 0; } else { event = 0; s_copyMode = 0; MENU_ADD_ITEM(STR_EDIT); MENU_ADD_ITEM(STR_INSERT_BEFORE); MENU_ADD_ITEM(STR_INSERT_AFTER); MENU_ADD_ITEM(STR_COPY); MENU_ADD_ITEM(STR_MOVE); MENU_ADD_ITEM(STR_DELETE); menuHandler = onExpoMixMenu; } } } break; case EVT_KEY_LONG(KEY_LEFT): case EVT_KEY_LONG(KEY_RIGHT): if (s_copyMode && !s_copyTgtOfs) { if (reachExpoMixCountLimit(expo)) break; s_currCh = chn; if (event == EVT_KEY_LONG(KEY_RIGHT)) { s_currIdx++; m_posVert++; } insertExpoMix(expo, s_currIdx); pushMenu(expo ? menuModelExpoOne : menuModelMixOne); s_copyMode = 0; killEvents(event); } break; case EVT_KEY_FIRST(KEY_MOVE_UP): case EVT_KEY_REPT(KEY_MOVE_UP): case EVT_KEY_FIRST(KEY_MOVE_DOWN): case EVT_KEY_REPT(KEY_MOVE_DOWN): if (s_copyMode) { uint8_t key = (event & 0x1f); uint8_t next_ofs = (key==KEY_MOVE_UP ? s_copyTgtOfs - 1 : s_copyTgtOfs + 1); if (s_copyTgtOfs==0 && s_copyMode==COPY_MODE) { // insert a mix on the same channel (just above / just below) if (reachExpoMixCountLimit(expo)) break; copyExpoMix(expo, s_currIdx); if (key==KEY_MOVE_DOWN) s_currIdx++; else if (sub-s_pgOfs >= 6) s_pgOfs++; } else if (next_ofs==0 && s_copyMode==COPY_MODE) { // delete the mix deleteExpoMix(expo, s_currIdx); if (key==KEY_MOVE_UP) s_currIdx--; } else { // only swap the mix with its neighbor if (!swapExpoMix(expo, s_currIdx, key==KEY_MOVE_UP)) break; eeDirty(EE_MODEL); } s_copyTgtOfs = next_ofs; } break; } if (expo) { lcd_outdezAtt(FW*sizeof(TR_MENUINPUTS)+FW+FW/2, 0, getExpoMixCount(true)); lcd_puts(FW*sizeof(TR_MENUINPUTS)+FW+FW/2, 0, STR_MAX(MAX_EXPOS)); // Value uint8_t index = expoAddress(s_currIdx)->chn; if (!s_currCh) { lcd_outdezAtt(127, 2, calcRESXto1000(anas[index]), PREC1|TINSIZE); } SIMPLE_MENU(STR_MENUINPUTS, menuTabModel, e_InputsAll, s_maxLines); // Gauge if (!s_currCh) { drawGauge(127, 1, 58, 6, anas[index], 1024); } } else { lcd_outdezAtt(FW*sizeof(TR_MIXER)+FW+FW/2, 0, getExpoMixCount(false)); lcd_puts(FW*sizeof(TR_MIXER)+FW+FW/2, 0, STR_MAX(MAX_MIXERS)); // Value uint8_t index = mixAddress(s_currIdx)->destCh; if (!s_currCh) { displayHeaderChannelName(index); lcd_outdezAtt(127, 2, calcRESXto1000(ex_chans[index]), PREC1|TINSIZE); } SIMPLE_MENU(STR_MIXER, menuTabModel, e_MixAll, s_maxLines); // Gauge if (!s_currCh) { drawGauge(127, 1, 58, 6, ex_chans[index], 1024); } } sub = m_posVert; s_currCh = 0; int cur = 0; int i = 0; for (int ch=1; ch<=(expo ? NUM_INPUTS : NUM_CHNOUT); ch++) { void *pointer = NULL; MixData * &md = (MixData * &)pointer; ExpoData * &ed = (ExpoData * &)pointer; coord_t y = MENU_HEADER_HEIGHT+1+(cur-s_pgOfs)*FH; if (expo ? (i<MAX_EXPOS && (ed=expoAddress(i))->chn+1 == ch && EXPO_VALID(ed)) : (i<MAX_MIXERS && (md=mixAddress(i))->srcRaw && md->destCh+1 == ch)) { if (cur-s_pgOfs >= 0 && cur-s_pgOfs < NUM_BODY_LINES) { if (expo) { putsMixerSource(0, y, ch, 0); } else { putsChn(0, y, ch, 0); // show CHx } } uint8_t mixCnt = 0; do { if (s_copyMode) { if (s_copyMode == MOVE_MODE && cur-s_pgOfs >= 0 && cur-s_pgOfs < NUM_BODY_LINES && s_copySrcCh == ch && s_copyTgtOfs != 0 && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { lcd_rect(expo ? 18 : 22, y-1, expo ? LCD_W-18 : LCD_W-22, 9, DOTTED); cur++; y+=FH; } if (s_currIdx == i) { sub = m_posVert = cur; s_currCh = ch; } } else if (sub == cur) { s_currIdx = i; } if (cur-s_pgOfs >= 0 && cur-s_pgOfs < NUM_BODY_LINES) { uint8_t attr = ((s_copyMode || sub != cur) ? 0 : INVERS); if (expo) { GVAR_MENU_ITEM(EXPO_LINE_WEIGHT_POS, y, ed->weight, MIN_EXPO_WEIGHT, 100, attr | (isExpoActive(i) ? BOLD : 0), 0, 0); displayExpoLine(y, ed); if (ed->mode!=3) { lcd_putc(EXPO_LINE_SIDE_POS, y, ed->mode == 2 ? 126 : 127); } } else { if (mixCnt > 0) lcd_putsiAtt(FW, y, STR_VMLTPX2, md->mltpx, 0); putsMixerSource(MIX_LINE_SRC_POS, y, md->srcRaw, 0); gvarWeightItem(MIX_LINE_WEIGHT_POS, y, md, attr | (isMixActive(i) ? BOLD : 0), 0); displayMixLine(y, md); char cs = ' '; if (md->speedDown || md->speedUp) cs = 'S'; if (md->delayUp || md->delayDown) cs = (cs =='S' ? '*' : 'D'); lcd_putc(MIX_LINE_DELAY_POS, y, cs); } if (s_copyMode) { if ((s_copyMode==COPY_MODE || s_copyTgtOfs == 0) && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { /* draw a border around the raw on selection mode (copy/move) */ lcd_rect(expo ? EXPO_LINE_SELECT_POS : 22, y-1, expo ? (LCD_W-EXPO_LINE_SELECT_POS) : (LCD_W-22), 9, s_copyMode == COPY_MODE ? SOLID : DOTTED); } if (cur == sub) { /* invert the raw when it's the current one */ drawFilledRect(expo ? EXPO_LINE_SELECT_POS+1 : 23, y, expo ? (LCD_W-EXPO_LINE_SELECT_POS-2) : (LCD_W-24), 7); } } } cur++; y+=FH; mixCnt++; i++; if (expo) ed++; else md++; } while (expo ? (i<MAX_EXPOS && ed->chn+1 == ch && EXPO_VALID(ed)) : (i<MAX_MIXERS && md->srcRaw && md->destCh+1 == ch)); if (s_copyMode == MOVE_MODE && cur-s_pgOfs >= 0 && cur-s_pgOfs < NUM_BODY_LINES && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { lcd_rect(expo ? EXPO_LINE_SELECT_POS : 22, y-1, expo ? LCD_W-EXPO_LINE_SELECT_POS : LCD_W-22, 9, DOTTED); cur++; y+=FH; } } else { uint8_t attr = 0; if (sub == cur) { s_currIdx = i; s_currCh = ch; if (!s_copyMode) { attr = INVERS; } } if (cur-s_pgOfs >= 0 && cur-s_pgOfs < NUM_BODY_LINES) { if (expo) { putsMixerSource(0, y, ch, attr); } else { putsChn(0, y, ch, attr); // show CHx } if (s_copyMode == MOVE_MODE && s_copySrcCh == ch) { lcd_rect(expo ? EXPO_LINE_SELECT_POS : 22, y-1, expo ? (LCD_W-EXPO_LINE_SELECT_POS) : (LCD_W-22), 9, DOTTED); } } cur++; y+=FH; } } s_maxLines = cur; if (sub >= s_maxLines-1) m_posVert = s_maxLines-1; }
void menuModelExpoOne(uint8_t event) { if (event == EVT_KEY_LONG(KEY_MENU)) { pushMenu(menuChannelsView); killEvents(event); } ExpoData *ed = expoAddress(s_currIdx); putsMixerSource(7*FW+FW/2, 0, MIXSRC_FIRST_INPUT+ed->chn, 0); SUBMENU(STR_MENUINPUTS, EXPO_FIELD_MAX, {0, 0, 0, ed->srcRaw >= MIXSRC_FIRST_TELEM ? (uint8_t)0 : (uint8_t)HIDDEN_ROW, 0, 0, CASE_CURVES(CURVE_ROWS) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0 /*, ...*/}); SET_SCROLLBAR_X(EXPO_ONE_2ND_COLUMN+10*FW); int8_t sub = m_posVert; coord_t y = MENU_HEADER_HEIGHT + 1; for (unsigned int k=0; k<NUM_BODY_LINES; k++) { int i = k + s_pgOfs; for (int j=0; j<=i; ++j) { if (j<(int)DIM(mstate_tab) && mstate_tab[j] == HIDDEN_ROW) { ++i; } } LcdFlags attr = (sub==i ? (s_editMode>0 ? BLINK|INVERS : INVERS) : 0); switch(i) { case EXPO_FIELD_INPUT_NAME: editSingleName(EXPO_ONE_2ND_COLUMN, y, STR_INPUTNAME, g_model.inputNames[ed->chn], sizeof(g_model.inputNames[ed->chn]), event, attr); break; case EXPO_FIELD_NAME: editSingleName(EXPO_ONE_2ND_COLUMN, y, STR_EXPONAME, ed->name, sizeof(ed->name), event, attr); break; case EXPO_FIELD_SOURCE: lcd_putsLeft(y, NO_INDENT(STR_SOURCE)); putsMixerSource(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw, STREXPANDED|attr); if (attr) ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isInputSourceAvailable); break; case EXPO_FIELD_SCALE: lcd_putsLeft(y, STR_SCALE); putsTelemetryChannelValue(EXPO_ONE_2ND_COLUMN, y, (ed->srcRaw - MIXSRC_FIRST_TELEM)/3, convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale), LEFT|attr); if (attr) ed->scale = checkIncDec(event, ed->scale, 0, maxTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1), EE_MODEL); break; case EXPO_FIELD_WEIGHT: lcd_putsLeft(y, STR_WEIGHT); ed->weight = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->weight, MIN_EXPO_WEIGHT, 100, LEFT|attr, 0, event); break; case EXPO_FIELD_OFFSET: lcd_putsLeft(y, NO_INDENT(STR_OFFSET)); ed->offset = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->offset, -100, 100, LEFT|attr, 0, event); break; #if defined(CURVES) case EXPO_FIELD_CURVE: lcd_putsLeft(y, STR_CURVE); editCurveRef(EXPO_ONE_2ND_COLUMN, y, ed->curve, event, attr); break; #endif #if defined(FLIGHT_MODES) case EXPO_FIELD_FLIGHT_MODES: ed->flightModes = editFlightModes(EXPO_ONE_2ND_COLUMN, y, event, ed->flightModes, attr); break; #endif case EXPO_FIELD_SWITCH: ed->swtch = switchMenuItem(EXPO_ONE_2ND_COLUMN, y, ed->swtch, attr, event); break; case EXPO_FIELD_SIDE: ed->mode = 4 - selectMenuItem(EXPO_ONE_2ND_COLUMN, y, STR_SIDE, STR_VSIDE, 4-ed->mode, 1, 3, attr, event); break; case EXPO_FIELD_TRIM: uint8_t not_stick = (ed->srcRaw > MIXSRC_Ail); int8_t carryTrim = -ed->carryTrim; lcd_putsLeft(y, STR_TRIM); lcd_putsiAtt(EXPO_ONE_2ND_COLUMN, y, STR_VMIXTRIMS, (not_stick && carryTrim == 0) ? 0 : carryTrim+1, m_posHorz==0 ? attr : 0); if (attr) ed->carryTrim = -checkIncDecModel(event, carryTrim, not_stick ? TRIM_ON : -TRIM_OFF, -TRIM_AIL); break; } y += FH; } DrawFunction(expoFn); int x512 = getValue(ed->srcRaw); if (ed->srcRaw >= MIXSRC_FIRST_TELEM) { putsTelemetryChannelValue(LCD_W-8, 6*FH, (ed->srcRaw - MIXSRC_FIRST_TELEM) / 3, x512, 0); if (ed->scale > 0) x512 = (x512 * 1024) / convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale); } else { lcd_outdezAtt(LCD_W-8, 6*FH, calcRESXto1000(x512), PREC1); } x512 = limit(-1024, x512, 1024); int y512 = expoFn(x512); y512 = limit(-1024, y512, 1024); lcd_outdezAtt(LCD_W-8-6*FW, 1*FH, calcRESXto1000(y512), PREC1); x512 = X0+x512/(RESX/WCHART); y512 = (LCD_H-1) - ((y512+RESX)/2) * (LCD_H-1) / RESX; lcd_vline(x512, y512-3, 3*2+1); lcd_hline(x512-3, y512, 3*2+1); }
void menuModelLimits(uint8_t event) { uint8_t sub = m_posVert - 1; if (sub < NUM_CHNOUT) { #if defined(PPM_CENTER_ADJUSTABLE) || defined(PPM_UNIT_US) lcd_outdezAtt(13*FW, 0, PPM_CH_CENTER(sub)+channelOutputs[sub]/2, 0); lcd_puts(13*FW, 0, STR_US); #else lcd_outdezAtt(13*FW, 0, calcRESXto1000(channelOutputs[sub]), PREC1); #endif } #if defined(CPUARM) MENU(STR_MENULIMITS, menuTabModel, e_Limits, 1+NUM_CHNOUT+1, {0, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, 0}); #else MENU(STR_MENULIMITS, menuTabModel, e_Limits, 1+NUM_CHNOUT+1, {0, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, 0}); #endif if (s_warning_result) { s_warning_result = 0; LimitData *ld = limitAddress(sub); ld->revert = !ld->revert; eeDirty(EE_MODEL); } for (uint8_t i=0; i<LCD_LINES-1; i++) { coord_t y = MENU_HEADER_HEIGHT + 1 + i*FH; uint8_t k = i+s_pgOfs; if (k==NUM_CHNOUT) { // last line available - add the "copy trim menu" line uint8_t attr = (sub==NUM_CHNOUT) ? INVERS : 0; lcd_putsAtt(CENTER_OFS, y, STR_TRIMS2OFFSETS, s_noHi ? 0 : attr); if (attr) { s_editMode = 0; if (event==EVT_KEY_LONG(KEY_ENTER)) { s_noHi = NO_HI_LEN; killEvents(event); moveTrimsToOffsets(); // if highlighted and menu pressed - move trims to offsets } } return; } LimitData *ld = limitAddress(k); #if !defined(PPM_CENTER_ADJUSTABLE) int16_t v = (ld->revert) ? -LIMIT_OFS(ld) : LIMIT_OFS(ld); char swVal = '-'; // '-', '<', '>' if ((channelOutputs[k] - v) > 50) swVal = (ld->revert ? 127 : 126); // Switch to raw inputs? - remove trim! if ((channelOutputs[k] - v) < -50) swVal = (ld->revert ? 126 : 127); putsChn(0, y, k+1, 0); lcd_putc(LIMITS_DIRECTION_POS, y, swVal); #endif int8_t limit = (g_model.extendedLimits ? LIMIT_EXT_MAX : 100); putsChn(0, y, k+1, 0); for (uint8_t j=0; j<ITEM_LIMITS_COUNT; j++) { uint8_t attr = ((sub==k && m_posHorz==j) ? ((s_editMode>0) ? BLINK|INVERS : INVERS) : 0); uint8_t active = (attr && (s_editMode>0 || p1valdiff)) ; if (active) STICK_SCROLL_DISABLE(); switch(j) { case ITEM_LIMITS_OFFSET: #if defined(PPM_UNIT_US) lcd_outdezAtt(LIMITS_OFFSET_POS, y, ((int32_t)ld->offset*128) / 25, attr|PREC1); #else lcd_outdezAtt(LIMITS_OFFSET_POS, y, ld->offset, attr|PREC1); #endif if (active) { #if defined(CPUARM) ld->offset = checkIncDec(event, ld->offset, -1000, 1000, EE_MODEL, NULL, stops1000); #else ld->offset = checkIncDec(event, ld->offset, -1000, 1000, EE_MODEL|NO_INCDEC_MARKS); #endif } else if (attr && event==EVT_KEY_LONG(KEY_MENU)) { copySticksToOffset(k); s_editMode = 0; } break; case ITEM_LIMITS_MIN: lcd_outdezAtt(LIMITS_MIN_POS, y, MIN_MAX_DISPLAY(ld->min-LIMITS_MIN_MAX_OFFSET), MIN_MAX_ATTR); #if defined(CPUARM) if (active) ld->min = LIMITS_MIN_MAX_OFFSET + checkIncDec(event, ld->min-LIMITS_MIN_MAX_OFFSET, -limit, 0, EE_MODEL, NULL, stops1000); #else if (active) ld->min = LIMITS_MIN_MAX_OFFSET + checkIncDec(event, ld->min-LIMITS_MIN_MAX_OFFSET, -limit, 0, EE_MODEL); #endif break; case ITEM_LIMITS_MAX: lcd_outdezAtt(LIMITS_MAX_POS, y, MIN_MAX_DISPLAY(ld->max+LIMITS_MIN_MAX_OFFSET), MIN_MAX_ATTR); #if defined(CPUARM) if (active) ld->max = -LIMITS_MIN_MAX_OFFSET + checkIncDec(event, ld->max+LIMITS_MIN_MAX_OFFSET, 0, +limit, EE_MODEL, NULL, stops1000); #else if (active) ld->max = -LIMITS_MIN_MAX_OFFSET + checkIncDec(event, ld->max+LIMITS_MIN_MAX_OFFSET, 0, +limit, EE_MODEL); #endif break; case ITEM_LIMITS_DIRECTION: { uint8_t revert = ld->revert; #if defined(PPM_CENTER_ADJUSTABLE) lcd_putcAtt(LIMITS_REVERT_POS, y, revert ? 127 : 126, attr); #else lcd_putsiAtt(LIMITS_REVERT_POS, y, STR_MMMINV, revert, attr); #endif if (active) { uint8_t revert_new = checkIncDecModel(event, revert, 0, 1); if (checkIncDec_Ret && isThrottleOutput(k)) { POPUP_CONFIRMATION(STR_INVERT_THR); } else { ld->revert = revert_new; } } break; } #if defined(PPM_CENTER_ADJUSTABLE) case ITEM_LIMITS_PPM_CENTER: lcd_outdezAtt(LIMITS_PPM_CENTER_POS, y, PPM_CENTER+ld->ppmCenter, attr); if (active) { CHECK_INCDEC_MODELVAR(event, ld->ppmCenter, -PPM_CENTER_MAX, +PPM_CENTER_MAX); } break; #endif #if defined(PPM_LIMITS_SYMETRICAL) case ITEM_LIMITS_SYMETRICAL: #if defined(CPUARM) lcd_putcAtt(LCD_W-FW-MENUS_SCROLLBAR_WIDTH, y, ld->symetrical ? '=' : '\306', attr); #else lcd_putcAtt(LCD_W-FW-MENUS_SCROLLBAR_WIDTH, y, ld->symetrical ? '=' : '^', attr); #endif if (active) { CHECK_INCDEC_MODELVAR_ZERO(event, ld->symetrical, 1); } break; #endif } } } }