void pushMenu(MenuFuncP newMenu) { killEvents(KEY_ENTER); if (g_menuStackPtr == 0) { if (newMenu == menuGeneralSetup) g_menuPos[0] = 1; if (newMenu == menuModelSelect) g_menuPos[0] = 0; } else { g_menuPos[g_menuStackPtr] = m_posVert; } g_menuStackPtr++; assert(g_menuStackPtr < DIM(g_menuStack)); AUDIO_MENUS(); g_menuStack[g_menuStackPtr] = newMenu; (*newMenu)(EVT_ENTRY); }
void check(check_event_t event, uint8_t curr, const MenuHandlerFunc *menuTab, uint8_t menuTabSize, const pm_uint8_t *horTab, uint8_t horTabMax, vertpos_t maxrow) { vertpos_t l_posVert = menuVerticalPosition; horzpos_t l_posHorz = menuHorizontalPosition; uint8_t maxcol = MAXCOL(l_posVert); #if defined(NAVIGATION_POT1) // check pot 1 - if changed -> scroll values static int16_t p1val; static int16_t p1valprev; p1valdiff = (p1val-calibratedStick[6]) / SCROLL_POT1_TH; if (p1valdiff) { p1valdiff = (p1valprev-calibratedStick[6]) / 2; p1val = calibratedStick[6]; } p1valprev = calibratedStick[6]; #endif #if defined(NAVIGATION_POT2) // check pot 2 - if changed -> scroll menu static int16_t p2valprev; p2valdiff = (p2valprev-calibratedStick[4]) / SCROLL_TH; if (p2valdiff) p2valprev = calibratedStick[4]; #endif #if defined(NAVIGATION_POT3) // check pot 3 if changed -> cursor down/up static int16_t p3valprev; int8_t scrollUD = (p3valprev-calibratedStick[5]) / SCROLL_TH; if (scrollUD) p3valprev = calibratedStick[5]; #else #define scrollUD 0 #endif if (p2valdiff || scrollUD || p1valdiff) backlightOn(); // on keypress turn the light on if (menuTab) { uint8_t attr = 0; if (l_posVert==0 && !calibrationState) { attr = INVERS; int8_t cc = curr; if (p2valdiff) { cc = limit((int8_t)0, (int8_t)(cc - p2valdiff), (int8_t)(menuTabSize-1)); } switch(event) { #if defined(ROTARY_ENCODER_NAVIGATION) case EVT_ROTARY_BREAK: if (s_editMode < 0 && maxrow > 0) { s_editMode = 0; // TODO ? l_posVert = (horTab && horTab[1]==0xff) ? 2 : 1; l_posHorz = 0; } else { s_editMode = -1; } event = 0; break; #endif #if defined(ROTARY_ENCODER_NAVIGATION) case EVT_ROTARY_LEFT: if (s_editMode >= 0) break; #endif case EVT_KEY_FIRST(KEY_LEFT): if (curr > 0) cc = curr - 1; else cc = menuTabSize-1; break; #if defined(ROTARY_ENCODER_NAVIGATION) case EVT_ROTARY_RIGHT: if (s_editMode >= 0) break; #endif case EVT_KEY_FIRST(KEY_RIGHT): if (curr < (menuTabSize-1)) cc = curr + 1; else cc = 0; break; } if (cc != curr) { chainMenu((MenuHandlerFunc)pgm_read_adr(&menuTab[cc])); } #if defined(ROTARY_ENCODER_NAVIGATION) if (IS_RE_NAVIGATION_ENABLE() && s_editMode < 0) attr = INVERS|BLINK; #endif } calibrationState = 0; displayScreenIndex(curr, menuTabSize, attr); } DISPLAY_PROGRESS_BAR(menuTab ? lcdLastPos-2*FW-((curr+1)/10*FWNUM)-2 : 20*FW+1); if (s_editMode<=0) { if (scrollUD) { l_posVert = limit((int8_t)0, (int8_t)(l_posVert - scrollUD), (int8_t)maxrow); l_posHorz = min((uint8_t)l_posHorz, MAXCOL(l_posVert)); } if (p2valdiff && l_posVert>0) { l_posHorz = limit((int8_t)0, (int8_t)((uint8_t)l_posHorz - p2valdiff), (int8_t)maxcol); } } switch(event) { case EVT_ENTRY: l_posVert = POS_VERT_INIT; l_posHorz = POS_HORZ_INIT(l_posVert); SET_SCROLLBAR_X(LCD_W-1); #if defined(ROTARY_ENCODER_NAVIGATION) if (menuTab) { s_editMode = EDIT_MODE_INIT; break; } // no break #else s_editMode = EDIT_MODE_INIT; break; #endif #if defined(ROTARY_ENCODER_NAVIGATION) case EVT_ENTRY_UP: s_editMode = 0; SET_SCROLLBAR_X(LCD_W-1); break; case EVT_ROTARY_BREAK: if (s_editMode > 1) break; #endif case EVT_KEY_FIRST(KEY_ENTER): if (!menuTab || l_posVert>0) { if (READ_ONLY_UNLOCKED()) { s_editMode = (s_editMode<=0); } } break; #if defined(ROTARY_ENCODER_NAVIGATION) case EVT_ROTARY_LONG: if (s_editMode > 1) break; killEvents(event); if (l_posVert != POS_VERT_INIT) { l_posVert = POS_VERT_INIT; s_editMode = EDIT_MODE_INIT; break; } // no break #endif case EVT_KEY_LONG(KEY_EXIT): s_editMode = 0; // TODO needed? we call ENTRY_UP after which does the same popMenu(); break; case EVT_KEY_BREAK(KEY_EXIT): #if defined(ROTARY_ENCODER_NAVIGATION) if (s_editMode == 0) s_editMode = EDIT_MODE_INIT; else #endif if (s_editMode>0) { s_editMode = 0; break; } if (l_posVert==0 || !menuTab) { popMenu(); // beeps itself } else { AUDIO_MENUS(); l_posVert = 0; l_posHorz = 0; } break; case EVT_KEY_REPT(KEY_RIGHT): //inc if (l_posHorz==maxcol) break; // no break case EVT_KEY_FIRST(KEY_RIGHT)://inc if (!horTab || s_editMode>0) break; #if defined(ROTARY_ENCODER_NAVIGATION) CASE_EVT_ROTARY_MOVE_RIGHT if (s_editMode != 0) break; if (l_posHorz < maxcol) { l_posHorz++; break; } else { l_posHorz = 0; if (!IS_ROTARY_MOVE_RIGHT(event)) break; } #else INC(l_posHorz, 0, maxcol); break; #endif case EVT_KEY_REPT(KEY_DOWN): //inc if (!IS_ROTARY_RIGHT(event) && l_posVert==maxrow) break; // no break case EVT_KEY_FIRST(KEY_DOWN): //inc if (s_editMode>0) break; do { INC(l_posVert, POS_VERT_INIT, maxrow); } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert)); #if defined(ROTARY_ENCODER_NAVIGATION) s_editMode = 0; // if we go down, we must be in this mode #endif l_posHorz = min(l_posHorz, MAXCOL(l_posVert)); break; case EVT_KEY_REPT(KEY_LEFT): //dec if (l_posHorz==0) break; // no break case EVT_KEY_FIRST(KEY_LEFT)://dec if (!horTab || s_editMode>0) break; #if defined(ROTARY_ENCODER_NAVIGATION) CASE_EVT_ROTARY_MOVE_LEFT if (s_editMode != 0) break; if (l_posHorz > 0) { l_posHorz--; break; } else if (IS_ROTARY_MOVE_LEFT(event) && s_editMode == 0) { l_posHorz = 0xff; } else { l_posHorz = maxcol; break; } #else DEC(l_posHorz, 0, maxcol); break; #endif case EVT_KEY_REPT(KEY_UP): //dec if (!IS_ROTARY_LEFT(event) && l_posVert==0) break; // no break case EVT_KEY_FIRST(KEY_UP): //dec if (s_editMode>0) break; do { DEC(l_posVert, POS_VERT_INIT, maxrow); } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert)); #if defined(ROTARY_ENCODER_NAVIGATION) s_editMode = 0; // if we go up, we must be in this mode #endif l_posHorz = min((uint8_t)l_posHorz, MAXCOL(l_posVert)); break; } uint8_t maxLines = menuTab ? LCD_LINES-1 : LCD_LINES-2; if (l_posVert<1) { menuVerticalOffset=0; } else { if (l_posVert>maxLines+menuVerticalOffset) { menuVerticalOffset = l_posVert-maxLines; } else if (l_posVert<=menuVerticalOffset) { menuVerticalOffset = l_posVert-1; } } menuVerticalPosition = l_posVert; menuHorizontalPosition = l_posHorz; #if !defined(CPUM64) // cosmetics on 9x if (menuVerticalOffset > 0) { l_posVert--; if (l_posVert == menuVerticalOffset && CURSOR_NOT_ALLOWED_IN_ROW(l_posVert)) { menuVerticalOffset = l_posVert-1; } } #endif }
void menuTelemetryNMEA2(uint8_t event) { static uint8_t ignore_break; switch(event) { // Menu navigation case EVT_KEY_BREAK(KEY_LEFT): if (ignore_break==1) { ignore_break=0; break;} chainMenu(menuTelemetryNMEA1); return; case EVT_KEY_BREAK(KEY_RIGHT): if (ignore_break==1) { ignore_break=0; break;} chainMenu(menuTelemetryNMEA3); return; case EVT_KEY_LONG(KEY_UP): NMEA_DisableRXD(); chainMenu(menuStatisticsView); return; case EVT_KEY_LONG(KEY_DOWN): NMEA_DisableRXD(); chainMenu(menuMainView); return; //Beep setting case EVT_KEY_LONG(KEY_LEFT): ignore_break = 1; beep_on=0; AUDIO_MENUS(); // short blip break; case EVT_KEY_LONG(KEY_RIGHT): ignore_break = 1; beep_on=1; AUDIO_MENUS(); // short blip break; //Altitude setting /* Set a home position for altitude. Normally used before starting the model when GPS has got a fix. MENU[short] --> alternating relative and absolute altitudes MENU[long] --> set home altitude to current EXIT[long] --> reset max altitude to 0 Switch ON / OFF short beep with positive lift LEFT[long] --> Positive lift Beep off RIGHT[long] --> Positive lift Beep on */ case EVT_KEY_BREAK(KEY_MENU): if (ignore_break==1) { ignore_break=0; break;} if (!home_alt) // umschalten zwischen absoluter und relativer H�he home_alt = save_alt; else home_alt=0; if (save_alt==0) // wenn noch keine Home H�he gesetzt war, wird sie es jetzt, weil sonst // das Umschalten keine Wirkung zeigt save_alt = home_alt = abs_alt; // absolute altitude AUDIO_MENUS(); // short blip for non negative lift break; case EVT_KEY_LONG(KEY_MENU): ignore_break = 1; save_alt = home_alt = abs_alt; // Home altitude auf aktuelle absolute H�he setzen AUDIO_MENUS(); // short blip for non negative lift break; case EVT_KEY_LONG(KEY_EXIT): // Max Altitude auf 0 zur�cksetzen max_alt=0; AUDIO_MENUS(); // short blip for non negative lift break; } title ('2'); lcd_puts ( 1*FW, 1*FH, PSTR("Altitude Sat Max")); lcd_puts ( 16*FW, 3*FH, PSTR("Home")); lcd_puts ( 2*FW, 4*FH, PSTR("Lift") ); lcd_puts ( 16*FW, 5*FH, PSTR("Beep") ); if (beep_on==1) lcd_puts ( 18*FW, 6*FH, PSTR("ON") ); else lcd_puts ( 17*FW, 6*FH, PSTR("OFF") ); lcd_outdezNAtt( 20*FW, 4*FH, home_alt, PREC1, 6); // display home_alt, small characters if (xpack[0] != PACK_GGA) ggareceived = 0; initval (LONG_BUF(0), PACK_GGA, ALT); // -> rbuf[0] initval (LONG_BUF(1), PACK_GGA, GEO); // -> rbuf[1] initval (SHORT_BUF(0), PACK_GGA, MTR); // -> sbuf[0] initval (SHORT_BUF(1), PACK_GGA, FIX); // -> sbuf[1] initval (SHORT_BUF(2), PACK_GGA, SAT); // -> sbuf[2] if (ggareceived) // at least one second has elapsed { ggareceived = 0; /* ALT and GEO have one single digit following the decimal point e.g. ALT=359.7 GEO=47.7 The altitude over mean sea level is to be calculated as: altitude minus geoidal separation */ abs_alt = binary(rbuf[0]) - binary(rbuf[1]); // alt - geo that is absolute altitude if (abs_alt> max_alt) max_alt=abs_alt; // hold max altitude relative to 0 m rel_alt=abs_alt - home_alt; // alt - geo - home altitude relative to home lift_alt = rel_alt - prev_alt; prev_alt = rel_alt; if ((lift_alt >= 0) && (sbuf[1]>0x30) && beep_on) // GGA record must have Fix> 0 AUDIO_MENUS(); // short blip for non negative lift } if (rbuf[0][0]) { lcd_putcAtt ( 13*FW, 1*FH, sbuf[2], 0); // satellites in view if (sbuf[1]>0x30) { // & GGA has FIX > 0 lcd_outdezNAtt( 10*FW, 2*FH, rel_alt, DBLSIZE|PREC1, 7); // altitude if (home_alt >= 0) lcd_outdezNAtt( 20*FW, 2*FH, (max_alt-home_alt), PREC1, 6); // display small characters else lcd_outdezNAtt( 20*FW, 2*FH, max_alt, PREC1, 6); // display small characters lcd_putcAtt ( 11*FW, 3*FH, sbuf[0], 0); // dimension [m] lcd_outdezNAtt( 10*FW, 5*FH, lift_alt, DBLSIZE|PREC1, 6); // lift lcd_putcAtt ( 11*FW, 6*FH, sbuf[0], 0); // dimension [m/S] lcd_puts ( 12*FW, 6*FH, PSTR("/S") ); } } else { lcd_putsAtt ( 2*FW, 2*FH, val_unknown, APSIZE); lcd_putsAtt ( 2*FW, 5*FH, val_unknown, APSIZE); } }
void chainMenu(MenuFuncP newMenu) { g_menuStack[g_menuStackPtr] = newMenu; (*newMenu)(EVT_ENTRY); AUDIO_MENUS(); }
void perMain() { #if defined(PCBSKY9X) && !defined(REVA) calcConsumption(); #endif checkSpeakerVolume(); checkEeprom(); sdMountPoll(); writeLogs(); handleUsbConnection(); checkTrainerSettings(); checkBattery(); uint8_t evt = getEvent(false); if (evt && (g_eeGeneral.backlightMode & e_backlight_mode_keys)) backlightOn(); // on keypress turn the light on checkBacklight(); #if defined(NAVIGATION_STICKS) uint8_t sticks_evt = getSticksNavigationEvent(); if (sticks_evt) evt = sticks_evt; #endif #if defined(USB_MASS_STORAGE) if (usbPlugged()) { // disable access to menus lcd_clear(); menuMainView(0); lcdRefresh(); return; } #endif #if defined(LUA) uint32_t t0 = get_tmr10ms(); static uint32_t lastLuaTime = 0; uint16_t interval = (lastLuaTime == 0 ? 0 : (t0 - lastLuaTime)); lastLuaTime = t0; if (interval > maxLuaInterval) { maxLuaInterval = interval; } // run Lua scripts that don't use LCD (to use CPU time while LCD DMA is running) luaTask(0, RUN_MIX_SCRIPT | RUN_FUNC_SCRIPT | RUN_TELEM_BG_SCRIPT, false); // wait for LCD DMA to finish before continuing, because code from this point // is allowed to change the contents of LCD buffer // // WARNING: make sure no code above this line does any change to the LCD display buffer! // lcdRefreshWait(); // draw LCD from menus or from Lua script // run Lua scripts that use LCD bool standaloneScriptWasRun = luaTask(evt, RUN_STNDAL_SCRIPT, true); bool refreshScreen = true; if (!standaloneScriptWasRun) { refreshScreen = !luaTask(evt, RUN_TELEM_FG_SCRIPT, true); } t0 = get_tmr10ms() - t0; if (t0 > maxLuaDuration) { maxLuaDuration = t0; } if (!standaloneScriptWasRun) #else lcdRefreshWait(); // WARNING: make sure no code above this line does any change to the LCD display buffer! const bool refreshScreen = true; #endif { // normal GUI from menus const char *warn = s_warning; uint8_t menu = s_menu_count; if (refreshScreen) { lcd_clear(); } if (menuEvent) { m_posVert = menuEvent == EVT_ENTRY_UP ? g_menuPos[g_menuStackPtr] : 0; m_posHorz = 0; evt = menuEvent; menuEvent = 0; AUDIO_MENUS(); } g_menuStack[g_menuStackPtr]((warn || menu) ? 0 : evt); if (warn) DISPLAY_WARNING(evt); if (menu) { const char * result = displayMenu(evt); if (result) { menuHandler(result); putEvent(EVT_MENU_UP); } } drawStatusLine(); } lcdRefresh(); #if defined(REV9E) && !defined(SIMU) topLcdRefreshStart(); setTopFirstTimer(getValue(MIXSRC_FIRST_TIMER+g_model.topLcdTimer)); setTopSecondTimer(g_eeGeneral.globalTimer + sessionTimer); setTopRssi(TELEMETRY_RSSI()); setTopBatteryValue(g_vbat100mV); setTopBatteryState(GET_TXBATT_BARS(), IS_TXBATT_WARNING()); topLcdRefreshEnd(); #endif #if defined(REV9E) && !defined(SIMU) bluetoothWakeup(); #endif #if defined(PCBTARANIS) if (requestScreenshot) { requestScreenshot = false; writeScreenshot(); } #endif }