Пример #1
0
void menuStatisticsView(uint8_t event)
{
  TITLE(STR_MENUSTAT);

  switch(event)
  {
    case EVT_KEY_FIRST(KEY_UP):
      chainMenu(menuStatisticsDebug);
      break;

    case EVT_KEY_LONG(KEY_MENU):
      g_eeGeneral.globalTimer = 0;
      eeDirty(EE_GENERAL);
      sessionTimer = 0;
      break;

    case EVT_KEY_FIRST(KEY_EXIT):
      chainMenu(menuMainView);
      break;
  }

  // Session and Total timers
  lcd_putsAtt(STATS_1ST_COLUMN, FH*1+1, "SES", BOLD);
  putsTimer(STATS_1ST_COLUMN + STATS_LABEL_WIDTH, FH*1+1, sessionTimer, 0, 0);
  lcd_putsAtt(STATS_1ST_COLUMN, FH*2+1, "TOT", BOLD);
  putsTimer(STATS_1ST_COLUMN + STATS_LABEL_WIDTH, FH*2+1, g_eeGeneral.globalTimer + sessionTimer, TIMEHOUR, 0);

  // Throttle special timers
  lcd_putsAtt(STATS_2ND_COLUMN, FH*0+1, "THR", BOLD);
  putsTimer(STATS_2ND_COLUMN + STATS_LABEL_WIDTH, FH*0+1, s_timeCumThr, 0, 0);
  lcd_putsAtt(STATS_2ND_COLUMN, FH*1+1, "TH%", BOLD);
  putsTimer(STATS_2ND_COLUMN + STATS_LABEL_WIDTH, FH*1+1, s_timeCum16ThrP/16, 0, 0);

  // Timers
  for (int i=0; i<TIMERS; i++) {
    putsStrIdx(STATS_3RD_COLUMN, FH*i+1, "TM", i+1, BOLD);
    if (timersStates[i].val > 3600)
      putsTimer(STATS_3RD_COLUMN + STATS_LABEL_WIDTH, FH*i+1, timersStates[i].val, TIMEHOUR, 0);
    else
      putsTimer(STATS_3RD_COLUMN + STATS_LABEL_WIDTH, FH*i+1, timersStates[i].val, 0, 0);
  }

#if defined(THRTRACE)
  coord_t traceRd = (s_traceCnt < 0 ? s_traceWr : 0);
  const coord_t x = 5;
  const coord_t y = 60;
  lcd_hline(x-3, y, MAXTRACE+3+3);
  lcd_vline(x, y-32, 32+3);

  for (coord_t i=0; i<MAXTRACE; i+=6) {
    lcd_vline(x+i+6, y-1, 3);
  }
  for (coord_t i=1; i<=MAXTRACE; i++) {
    lcd_vline(x+i, y-s_traceBuf[traceRd], s_traceBuf[traceRd]);
    traceRd++;
    if (traceRd>=MAXTRACE) traceRd = 0;
    if (traceRd==s_traceWr) break;
  }
#endif
}
Пример #2
0
void menuProcArduPilot5(uint8_t event)
{
    switch(event)
    {
    case EVT_KEY_FIRST(KEY_UP):
        chainMenu(menuProcArduPilot4);
        break;
    case EVT_KEY_FIRST(KEY_DOWN):
        chainMenu(menuProcArduPilot6);
        break;
    case EVT_KEY_FIRST(KEY_MENU):
        break;
    case EVT_KEY_FIRST(KEY_EXIT):
        ARDUPILOT_DisableRXD();
        chainMenu(menuProc0);
    break;
    }
    initval (0, PACK_POS, WPN);
    initval (1, PACK_POS, DST);
    title ('5'); 
    lcd_puts_P  (1*FW, 1*FH, PSTR(" Way Point # "));    
    lcd_putsAtt (2*FW, 2*FH, VALSTR(0), APSIZE);
    lcd_puts_P  (1*FW, 4*FH, PSTR(" Distance "));
    lcd_putsAtt (2*FW, 5*FH, VALSTR(1), APSIZE);
}
Пример #3
0
void menuProcArduPilot6(uint8_t event)
{
    switch(event)
    {
    case EVT_KEY_FIRST(KEY_UP):
        chainMenu(menuProcArduPilot5);
        break;
    case EVT_KEY_FIRST(KEY_DOWN):
        chainMenu(menuProcArduPilot7);
        break;
    case EVT_KEY_FIRST(KEY_MENU):
        break;
    case EVT_KEY_FIRST(KEY_EXIT):
        ARDUPILOT_DisableRXD();
        chainMenu(menuProc0);
        break;
    }
    initval (0, PACK_ATT, ASP);
    initval (1, PACK_ATT, THH);
    title ('6'); 
    lcd_puts_P  (1*FW, 1*FH, PSTR(" Air Speed "));    
    lcd_putsAtt (2*FW, 2*FH, VALSTR(0), APSIZE);
    lcd_puts_P  (1*FW, 4*FH, PSTR(" Climb Rate "));
    lcd_putsAtt (2*FW, 5*FH, VALSTR(1), APSIZE);
}
Пример #4
0
void menuProcArduPilot7(uint8_t event)
{
    switch(event)
    {
    case EVT_KEY_FIRST(KEY_UP):
        chainMenu(menuProcArduPilot6);
        break;
    case EVT_KEY_FIRST(KEY_DOWN):
        chainMenu(menuProcArduPilot8);
        break;
    case EVT_KEY_FIRST(KEY_MENU):
        break;
    case EVT_KEY_FIRST(KEY_EXIT):
        ARDUPILOT_DisableRXD();
        chainMenu(menuProc0);
    break;
    }
    initval (0, PACK_ATT, RLL);
    initval (1, PACK_ATT, PCH);
    title ('7'); 
    lcd_puts_P  (1*FW, 1*FH, PSTR(" Roll Angle"));   
    lcd_putsAtt (2*FW, 2*FH, VALSTR(0), APSIZE);
    lcd_puts_P  (1*FW, 4*FH, PSTR(" Pitch Angle"));
    lcd_putsAtt (2*FW, 5*FH, VALSTR(1), APSIZE);
}
Пример #5
0
void menuProcArduPilot8(uint8_t event)
{
    switch(event)
    {
    case EVT_KEY_FIRST(KEY_UP):
        chainMenu(menuProcArduPilot7);
        break;
    case EVT_KEY_FIRST(KEY_DOWN):
        chainMenu(menuProcArduPilot1);
        break;
    case EVT_KEY_FIRST(KEY_MENU):
        break;
    case EVT_KEY_FIRST(KEY_EXIT):
        ARDUPILOT_DisableRXD();
        chainMenu(menuProc0);
        break;
    }
    initval (0, PACK_MOD, MOD);
    initval (1, PACK_WPC, WPC);
    title ('8');
    lcd_puts_P  (1*FW, 1*FH, PSTR(" ArduPilot Mode"));
    lcd_putsAtt (2*FW, 2*FH, VALSTR(0), APSIZE);
    lcd_puts_P  (1*FW, 4*FH, PSTR(" RTL Distance"));
    lcd_putsAtt (2*FW, 5*FH, VALSTR(1), APSIZE);
}
Пример #6
0
/*!	\brief Top Mavlink Menu definition
 *	\details Registers button events and handles that info. Buttons select menus,
 *	these are launched from the MAVLINK_menu switch statement. Setup menu is
 *	lanuched by the menu button. On exit (with exit button) the mavlink
 *	extension is reinitialized.
 */
void menuTelemetryMavlink(uint8_t event) {
	
	switch (event) // new event received, branch accordingly
	{
	case EVT_ENTRY:
		MAVLINK_menu = MENU_INFO;
		break;

	case EVT_KEY_FIRST(KEY_UP):
		if (MAVLINK_menu > 0)
		{
			MAVLINK_menu--;
			break;
		}
		else
		{
			chainMenu(menuMainView);
			return;
		}
	case EVT_KEY_FIRST(KEY_DOWN):
		if (MAVLINK_menu < MAX_MAVLINK_MENU - 1)
			MAVLINK_menu++;
		break;
	case EVT_KEY_FIRST(KEY_MENU):
		return;
	case EVT_KEY_FIRST(KEY_EXIT):
		chainMenu(menuMainView);
		return;
	}

	switch (MAVLINK_menu) {
	case MENU_INFO:
		menuTelemetryMavlinkInfos();
		break;
	case MENU_MODE:
		menuTelemetryMavlinkFlightMode();
		break;
	case MENU_BATT:
		menuTelemetryMavlinkBattery();
		break;
	case MENU_NAV:
		menuTelemetryMavlinkNavigation();
		break;
	case MENU_GPS:
		menuTelemetryMavlinkGPS();
		break;
#ifdef DUMP_RX_TX
	case MENU_DUMP_TX:
	case MENU_DUMP_RX:
		menuTelemetryMavlinkDump(event);
		break;
#endif
	default:
		break;
	}

}
Пример #7
0
void menuStatisticsView(uint8_t event)
{
  TITLE(STR_MENUSTAT);

  switch(event)
  {
    case EVT_KEY_FIRST(KEY_UP):
      chainMenu(menuStatisticsDebug);
      return;

#if defined(CPUARM)
    case EVT_KEY_LONG(KEY_MENU):
      g_eeGeneral.globalTimer = 0;
      eeDirty(EE_GENERAL);
      sessionTimer = 0;
      break;
#endif
    case EVT_KEY_FIRST(KEY_EXIT):
      chainMenu(menuMainView);
      return;
  }

  lcd_puts(  1*FW, FH*0, STR_TOTTM1TM2THRTHP);
  putsTimer(    5*FW+5*FWNUM+1, FH*1, timersStates[0].val, 0, 0);
  putsTimer(   12*FW+5*FWNUM+1, FH*1, timersStates[1].val, 0, 0);

  putsTimer(    5*FW+5*FWNUM+1, FH*2, s_timeCumThr, 0, 0);
  putsTimer(   12*FW+5*FWNUM+1, FH*2, s_timeCum16ThrP/16, 0, 0);

  putsTimer(   12*FW+5*FWNUM+1, FH*0, sessionTimer, 0, 0);
  
#if defined(CPUARM)
  putsTimer(21*FW+5*FWNUM+1, 0*FH, g_eeGeneral.globalTimer + sessionTimer, TIMEHOUR, 0);
#endif

#if defined(THRTRACE)
  uint8_t traceRd = (s_traceCnt < 0 ? s_traceWr : 0);
  const uint8_t x=5;
  const uint8_t y=60;
  lcd_hline(x-3,y,MAXTRACE+3+3);
  lcd_vline(x,y-32,32+3);

  for (uint8_t i=0; i<MAXTRACE; i+=6) {
    lcd_vline(x+i+6,y-1,3);
  }
  for (uint8_t i=1; i<=MAXTRACE; i++) {
    lcd_vline(x+i, y-s_traceBuf[traceRd], s_traceBuf[traceRd]);
    traceRd++;
    if (traceRd>=MAXTRACE) traceRd = 0;
    if (traceRd==s_traceWr) break;
  }
#endif
}
Пример #8
0
void menuProcNMEA4(uint8_t event)
{
    switch(event)						// new event received, branch accordingly
    {
    case EVT_KEY_BREAK(KEY_LEFT):
        chainMenu(menuProcNMEA3);
        break;
    case EVT_KEY_BREAK(KEY_RIGHT):
        chainMenu(menuProcNMEA1);
        break;
    case EVT_KEY_LONG(KEY_UP):
        NMEA_DisableRXD();
        chainMenu(menuProcStatistic);
        break;
    case EVT_KEY_LONG(KEY_DOWN):
        NMEA_DisableRXD();
        chainMenu(menuProc0);
        break;
    }
    // expecting LAT value in POS packet to be stored in the first buffer
    initval (LONG_BUF(0), PACK_GGA, LAT);
    initval (SHORT_BUF(0), PACK_GGA, NOS);
    // and LON value in POS packet stored in the second buffer
    initval (LONG_BUF(1), PACK_GGA, LON);
    initval (SHORT_BUF(1), PACK_GGA, EOW);
    initval (SHORT_BUF(2), PACK_GGA, SAT);			// -> sbuf[2]
    // title of the screen
    title ('4');
    lcd_puts_P        (   3*FW,   1*FH, PSTR("Latitude     Sat"));    // line 1 column 3
    // first buffer into line 2 column 2
    if (rbuf[0][0])
    {
        lcd_putcAtt   (  13*FW,   1*FH, sbuf[0], 0);          // N or S
	  lcd_putcAtt   (  19*FW,   1*FH, sbuf[2], 0);				// satellites in view
        lcd_putsnAtt  (   1*FW,   2*FH, rbuf[0], 2, APSIZE);
        lcd_putcAtt   (   5*FW,   2*FH, '@',0);
        lcd_putsAtt   (   6*FW,   2*FH, &rbuf[0][2], APSIZE);	// minutes with small decimal point
    }
    else
        lcd_putsAtt   (   2*FW,   2*FH, val_unknown, APSIZE);
    lcd_puts_P        (   3*FW,   4*FH, PSTR("Longitude"));   // line 4 column 5
    // second buffer into line 5 column 2
    if (rbuf[0][0])
    {
        lcd_putcAtt   (  13*FW,   4*FH, sbuf[1], 0);          // E or W
        lcd_putsnAtt  (   0*FW,   5*FH, rbuf[1], 3, APSIZE);
        lcd_putcAtt   (   6*FW,   5*FH, '@',0);
        lcd_putsAtt   (   7*FW,   5*FH, &rbuf[1][3], APSIZE);	// minutes with small decimal point

    }
    else
        lcd_putsAtt   (   2*FW,   5*FH, val_unknown, APSIZE);
}
Пример #9
0
void *main_thread(void *)
{
#ifdef SIMU_EXCEPTIONS
  signal(SIGFPE, sig);
  signal(SIGSEGV, sig);

  try {
#endif
    eeReadAll(); //load general setup and selected model

    if (main_thread_running == 1) {
      checkMem();  //enough eeprom free?
      checkTHR();
      checkSwitches(); //must be last
    }

    chainMenu(menuProc0); //call evt_entry

    while (main_thread_running) {
      perMain();
      sleep(1/*ms*/);
    }
#ifdef SIMU_EXCEPTIONS
  }
  catch (...) {
    main_thread_running = 0;
  }
#endif

  return NULL;
}
Пример #10
0
void menuProcNMEA3(uint8_t event)
{
    switch(event)
    {
    case EVT_KEY_BREAK(KEY_LEFT):
        chainMenu(menuProcNMEA2);
        break;
    case EVT_KEY_BREAK(KEY_RIGHT):
        chainMenu(menuProcNMEA4);
        break;
    case EVT_KEY_LONG(KEY_UP):
        NMEA_DisableRXD();
        chainMenu(menuProcStatistic);
        break;
    case EVT_KEY_LONG(KEY_DOWN):
        NMEA_DisableRXD();
        chainMenu(menuProc0);
        break;
    }
    initval (LONG_BUF(0), PACK_RMC, SOG);
    initval (LONG_BUF(1), PACK_RMC, COG);
    initval (SHORT_BUF(2), PACK_GGA, SAT);			// -> sbuf[2]
    title ('3');
    lcd_puts_P        (   0*FW,   1*FH, PSTR("GrndSpeed[knt]  Sat"));
    if (rbuf[0][0])				// if first position is 00, buffer is empty, taken as false 
    {							// any other value is true
        uint8_t i = 0;
        while (rbuf[0][i])
        {
            if (rbuf[0][i] == '.')		// find decimal point and insert End of String 3 positions higher
            {
                rbuf[0][i+3] = 0;
                break;
            }
            i++;
        }
        lcd_putsAtt   (   2*FW,   2*FH, VALSTR(0), APSIZE);		// speed over ground
    }
    else
        lcd_putsAtt   (   2*FW,   2*FH, val_unknown, APSIZE);

    lcd_putcAtt   (  19*FW,   1*FH, sbuf[2], 0);			// satellites in view

    lcd_puts_P        (   1*FW,   4*FH, PSTR("Course over ground") );
    lcd_putsAtt       (   2*FW,   5*FH, VALSTR(1), APSIZE);		// course over ground
}
Пример #11
0
void menuProcStatistic(uint8_t event)
{
  TITLE("STAT");
  switch(event)
  {
    case EVT_KEY_FIRST(KEY_UP):
      chainMenu(menuProcStatistic2);
      break;
    case EVT_KEY_FIRST(KEY_DOWN):
    case EVT_KEY_FIRST(KEY_EXIT):
      chainMenu(menuMainView);
      break;
  }

  lcd_puts_P(  1*FW, FH*1, PSTR("TME"));
  putsTime(    5*FW, FH*1, s_timeCumAbs, 0, 0);
  lcd_puts_P( 17*FW, FH*1, PSTR("TSW"));
  putsTime(   11*FW, FH*1, s_timeCumSw,      0, 0);

  lcd_puts_P(  1*FW, FH*2, PSTR("STK"));
  putsTime(    5*FW, FH*2, s_timeCumThr, 0, 0);
  lcd_puts_P( 17*FW, FH*2, PSTR("ST%"));
  putsTime(   11*FW, FH*2, s_timeCum16ThrP/16, 0, 0);

  lcd_puts_P( 17*FW, FH*0, PSTR("TOT"));
  putsTime(   11*FW, FH*0, s_timeCumTot, 0, 0);

  uint16_t traceRd = s_traceCnt>MAXTRACE ? s_traceWr : 0;
  uint8_t x=5;
  uint8_t y=60;
  lcd_hline(x-3,y,120+3+3);
  lcd_vline(x,y-32,32+3);

  for(uint8_t i=0; i<120; i+=6)
  {
    lcd_vline(x+i+6,y-1,3);
  }
  for(uint8_t i=1; i<=120; i++)
  {
    lcd_vline(x+i,y-s_traceBuf[traceRd],s_traceBuf[traceRd]);
    traceRd++;
    if(traceRd>=MAXTRACE) traceRd=0;
    if(traceRd==s_traceWr) break;
  }
}
Пример #12
0
void onMainViewMenu(const char *result)
{
  if (result == STR_RESET_TIMER1) {
    timerReset(0);
  }
  else if (result == STR_RESET_TIMER2) {
    timerReset(1);
  }
#if TIMERS > 2
  else if (result == STR_RESET_TIMER3) {
    timerReset(2);
  }
#endif
#if defined(CPUARM)
  else if (result == STR_VIEW_NOTES) {
    pushModelNotes();
  }
  else if (result == STR_RESET_SUBMENU) {
    MENU_ADD_ITEM(STR_RESET_FLIGHT);
    MENU_ADD_ITEM(STR_RESET_TIMER1);
    MENU_ADD_ITEM(STR_RESET_TIMER2);
    MENU_ADD_ITEM(STR_RESET_TIMER3);
#if defined(FRSKY)
    MENU_ADD_ITEM(STR_RESET_TELEMETRY);
#endif
  }
#endif
#if defined(FRSKY)
  else if (result == STR_RESET_TELEMETRY) {
    telemetryReset();
  }
#endif
  else if (result == STR_RESET_FLIGHT) {
    flightReset();
  }
  else if (result == STR_STATISTICS) {
    chainMenu(menuStatisticsView);
  }
#if defined(CPUARM)
  else if (result == STR_ABOUT_US) {
    chainMenu(menuAboutView);
  }
#endif
}
Пример #13
0
void menuFirstCalib(uint8_t event)
{
  if (event == EVT_KEY_BREAK(KEY_EXIT) || reusableBuffer.calib.state == 4) {
    chainMenu(menuMainView);
  }
  else {
    lcd_putsCenter(0*FH, MENUCALIBRATION);
    lcd_invert_line(0);
    menuCommonCalib(event);
  }
}
Пример #14
0
void menuTelemetryFrsky(uint8_t event)
{
  enum NavigationDirection direction = none;

  switch (event) {
    case EVT_KEY_FIRST(KEY_EXIT):
    case EVT_KEY_LONG(KEY_EXIT):
      killEvents(event);
      chainMenu(menuMainView);
      break;

    case EVT_KEY_LONG(KEY_PAGE):
      killEvents(event);
      // no break;

    case EVT_KEY_FIRST(KEY_UP):
      decrTelemetryScreen();
      break;

    case EVT_KEY_BREAK(KEY_PAGE):
    case EVT_KEY_FIRST(KEY_DOWN):
      incrTelemetryScreen();
      break;

    case EVT_KEY_LONG(KEY_ENTER):
      killEvents(event);
      POPUP_MENU_ADD_ITEM(STR_RESET_TELEMETRY);
      POPUP_MENU_ADD_ITEM(STR_RESET_FLIGHT);
      popupMenuHandler = onMainViewMenu;
      break;
  }

  for (int i=0; i<=TELEMETRY_SCREEN_TYPE_MAX; i++) {
    if (direction == up) {
      if (s_frsky_view-- == 0)
        s_frsky_view = TELEMETRY_VIEW_MAX;
    }
    else if (direction == down) {
      if (s_frsky_view++ == TELEMETRY_VIEW_MAX)
        s_frsky_view = 0;
    }
    else {
      direction = down;
    }
    if (displayTelemetryScreen()) {
      return;
    }
  }

  lcdDrawTelemetryTopBar();
  lcd_puts(8*FW, 3*FH, "No Telemetry Screens");
  displayRssiLine();
}
Пример #15
0
void menuProcArduPilot3(uint8_t event)
{
    switch(event)
    {
    case EVT_KEY_FIRST(KEY_UP):
        chainMenu(menuProcArduPilot2);
        break;
    case EVT_KEY_FIRST(KEY_DOWN):
        chainMenu(menuProcArduPilot4);
        break;
    case EVT_KEY_FIRST(KEY_EXIT):
        ARDUPILOT_DisableRXD();
        chainMenu(menuProc0);
        break;
    }
    initval (0, PACK_POS, ALT);
    initval (1, PACK_POS, ALH);
    title ('3');  
    lcd_puts_P  (1*FW, 1*FH, PSTR(" Altitude"));    
    lcd_putsAtt (2*FW, 2*FH, VALSTR(0), APSIZE);
    lcd_puts_P  (1*FW, 4*FH, PSTR(" Altitude Hold") );
    lcd_putsAtt (2*FW, 5*FH, VALSTR(1), APSIZE);
}
Пример #16
0
void menuProcArduPilot4(uint8_t event)
{
    switch(event)
    {
    case EVT_KEY_FIRST(KEY_UP):
        chainMenu(menuProcArduPilot3);
        break;
    case EVT_KEY_FIRST(KEY_DOWN):
        chainMenu(menuProcArduPilot5);
        break;
    case EVT_KEY_FIRST(KEY_EXIT):
        ARDUPILOT_DisableRXD();
        chainMenu(menuProc0);
    break;
    }
    initval (0, PACK_POS, CRS);
    initval (1, PACK_POS, BER);
    title ('4'); 
    lcd_puts_P  (1*FW, 1*FH, PSTR(" Course"));    
    lcd_putsAtt (2*FW, 2*FH, VALSTR(0), APSIZE);
    lcd_puts_P  (1*FW, 4*FH, PSTR(" Bearing"));
    lcd_putsAtt (2*FW, 5*FH, VALSTR(1), APSIZE);
}
Пример #17
0
void menuProcArduPilot2(uint8_t event)
{
    switch(event)
    {
    case EVT_KEY_FIRST(KEY_UP):
        chainMenu(menuProcArduPilot1);
        break;
    case EVT_KEY_FIRST(KEY_DOWN):
        chainMenu(menuProcArduPilot3);
        break;
    case EVT_KEY_FIRST(KEY_EXIT):
        ARDUPILOT_DisableRXD();
        chainMenu(menuProc0);
        break;
    }
    initval (0, PACK_POS, SPD);
    initval (1, PACK_POS, CRT);
    title ('2');  
    lcd_puts_P  (1*FW, 1*FH, PSTR(" Ground speed"));    
    lcd_putsAtt (2*FW, 2*FH, VALSTR(0), APSIZE);
    lcd_puts_P  (1*FW, 4*FH, PSTR(" Climb rate") );
    lcd_putsAtt (2*FW, 5*FH, VALSTR(1), APSIZE);
}
Пример #18
0
void menuTelemetryJeti(uint8_t event)
{
  lcdDrawTelemetryTopBar();

  for (uint8_t i=0; i<16; i++) {
    lcd_putcAtt((i+2)*FW, 3*FH, jetiRxBuffer[i], BSS);
    lcd_putcAtt((i+2)*FW, 4*FH, jetiRxBuffer[i+16], BSS);
  }

  if (event == EVT_KEY_FIRST(KEY_EXIT)) {
    JETI_DisableRXD();
    jetiReady = 0;
    chainMenu(menuMainView);
  }
}
Пример #19
0
void menuProcStatistic2(uint8_t event)
{
  TITLE("STAT2");
  switch(event)
  {
    case EVT_KEY_FIRST(KEY_MENU):
      g_tmr1Latency_min = 0xff;
      g_tmr1Latency_max = 0;
      g_timeMain    = 0;
//      g_time_per10 = 0;
      beepKey();
      break;
    case EVT_KEY_FIRST(KEY_DOWN):
      chainMenu(menuProcStatistic);
      break;
    case EVT_KEY_FIRST(KEY_UP):
    case EVT_KEY_FIRST(KEY_EXIT):
      chainMenu(menuMainView);
      break;
  }
  lcd_puts_P( 0*FW,  1*FH, PSTR("tmr1Lat max    us"));
  lcd_outdez8(15*FW , 1*FH, g_tmr1Latency_max/2 );
  lcd_puts_P( 0*FW,  2*FH, PSTR("tmr1Lat min    us"));
  lcd_outdez8(15*FW , 2*FH, g_tmr1Latency_min/2 );
  lcd_puts_P( 0*FW,  3*FH, PSTR("tmr1 Jitter    us"));
  lcd_outdez8(15*FW , 3*FH, (g_tmr1Latency_max - g_tmr1Latency_min) /2 );
  lcd_puts_P( 0*FW,  4*FH, PSTR("tmain max      ms"));
  lcd_outdezAtt(15*FW, 4*FH, (g_timeMain*100)/16, PREC2);
  lcd_puts_P( 0*FW,  5*FH, PSTR("t10ms          us"));
  lcd_outdez8(15*FW , 5*FH, g_time_per10/2 );
#ifndef SIMU
  lcd_puts_P( 0*FW,  6*FH, PSTR("Free Stack min    b"));
  lcd_outdezAtt(18*FW-1,  6*FH, stack_free() ) ;
#endif
  lcd_puts_P( 3*FW,  7*FH, PSTR("[MENU] to reset"));
}
Пример #20
0
void menuProcJeti(uint8_t event)
{
  TITLE("JETI");

  switch(event)
  {
    //case EVT_KEY_FIRST(KEY_MENU):
    //  break;
    case EVT_KEY_FIRST(KEY_EXIT):
      JETI_DisableRXD();
      chainMenu(menuProc0);
      break;
  }

  for (uint8_t i = 0; i < 16; i++)
  {
    lcd_putcAtt((i+2)*FW,   3*FH, JetiBuffer[i], BSS);
    lcd_putcAtt((i+2)*FW,   4*FH, JetiBuffer[i+16], BSS);
  }

  if (JetiBufferReady)
  {
    JETI_EnableTXD();
    if (keyState((EnumKeys)(KEY_UP))) jeti_keys &= JETI_KEY_UP;
    if (keyState((EnumKeys)(KEY_DOWN))) jeti_keys &= JETI_KEY_DOWN;
    if (keyState((EnumKeys)(KEY_LEFT))) jeti_keys &= JETI_KEY_LEFT;
    if (keyState((EnumKeys)(KEY_RIGHT))) jeti_keys &= JETI_KEY_RIGHT;

    JetiBufferReady = 0;    // invalidate buffer

    JETI_putw((uint16_t) jeti_keys);
    _delay_ms (1);
    JETI_DisableTXD();

    jeti_keys = JETI_KEY_NOCHANGE;
  }
}
Пример #21
0
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
}
Пример #22
0
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
}
Пример #23
0
void menuProcNMEA2(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(menuProcNMEA1);
        break;
    case EVT_KEY_BREAK(KEY_RIGHT):
          if (ignore_break==1) {
		     ignore_break=0;
                 break;}
        chainMenu(menuProcNMEA3);
        break;
    case EVT_KEY_LONG(KEY_UP):
        NMEA_DisableRXD();
        chainMenu(menuProcStatistic);
        break;
    case EVT_KEY_LONG(KEY_DOWN):
        NMEA_DisableRXD();
        chainMenu(menuProc0);
        break;

//Beep setting
    case EVT_KEY_LONG(KEY_LEFT):
	  ignore_break = 1;
        beep_on=0;
        audioDefevent(AU_MENUS); 						// short blip 
        break;
    case EVT_KEY_LONG(KEY_RIGHT):
	  ignore_break = 1;
        beep_on=1;
        audioDefevent(AU_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
        audioDefevent(AU_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
        audioDefevent(AU_MENUS); 						// short blip for non negative lift
        break;

    case EVT_KEY_LONG(KEY_EXIT):		// Max Altitude auf 0 zurücksetzen
	  max_alt=0;
        audioDefevent(AU_MENUS); 						// short blip for non negative lift
        break;

    }
    title ('2');
    
    lcd_puts_P         (   1*FW,   1*FH, PSTR("Altitude Sat   Max"));


    lcd_puts_P         (   16*FW,   3*FH, PSTR("Home"));
    lcd_puts_P         (   2*FW,   4*FH, PSTR("Lift") );

    lcd_puts_P         (   16*FW,   5*FH, PSTR("Beep") );
    if (beep_on==1)
        lcd_puts_P         (   18*FW,   6*FH, PSTR("ON") );
    
    else	
        lcd_puts_P         (   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	
            audioDefevent(AU_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_P    (  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);
    }
}
Пример #24
0
void menuProcNMEA1(uint8_t event)
{
    switch(event)						// new event received, branch accordingly
    {
    case EVT_KEY_BREAK(KEY_LEFT):
        chainMenu(menuProcNMEA4);
        break;
    case EVT_KEY_BREAK(KEY_RIGHT):
        chainMenu(menuProcNMEA2);
        break;
    case EVT_KEY_LONG(KEY_UP):
        NMEA_DisableRXD();
        chainMenu(menuProcStatistic);
        break;
    case EVT_KEY_LONG(KEY_DOWN):
        NMEA_DisableRXD();
        chainMenu(menuProc0);
        break;
    case EVT_KEY_FIRST(KEY_MENU):
        if (show_timer == 0) {
            show_timer = 1;
            if (gpstimer <= 0)
                gpstimer = bintime(rbuf[2]);
        }
        else
            show_timer = 0;
        break;
    case EVT_KEY_FIRST(KEY_EXIT):
        if ((show_timer == 1) &&(rbuf[2][0]))
            gpstimer = bintime(rbuf[2]);		// get actual GPS time ->resets timer to 00:00
        break;
    }
    /*
    How to use:

    You choose the values to be displayed using the function:

      initval(<number>, <packet>, <value>);
      -------------------------------------

    That means that "<value>" of "<packet>" is stored in the <number> buffer.
    The first <number> is 0.

    Here are the packet names and the associated value names:

    Position packet (beginning with "GGA"): "PACK_GGA"
    value names: "TIM", "LAT", "NOS", "LON", "EOW", "FIX", "SAT", "DIL", "ALT", "MTR", "GEO", "MET", "AGE", "DIF",

    Required minimum packet (beginning with "RMC"): "PACK_RMC"
       value names: "TIM", "NRW", "LT1", "NSO", "LN1", "EWE", "SOG", "COG", "DAT", "MAG", "EAW"

    The buffers are accessed using the macro "VALSTR(<n>)", where "<n>" is "0"
    for the first buffer, and "1" for the second buffer.

    When a value is missing, it is replaced by the contents of val_unknown ("?").
*/

    if (ggareceived)
    {
        gpstime=bintime(rbuf[2]);
        ggareceived=0;
    }

    initval (LONG_BUF(0), PACK_RMC, TIM);					// sets rbuf[0][.]
    initval (LONG_BUF(1), PACK_RMC, DAT);					// sets rbuf[1][.]
    initval (SHORT_BUF(0), PACK_RMC, NRW);				// sets sbuf[0]
    initval (SHORT_BUF(2), PACK_GGA, SAT);				// -> sbuf[2]


    title ('1');
    lcd_puts_P        (   2*FW,   1*FH, PSTR("UTC-Time      Sat"));

    if (rbuf[0][0]) {								// show always if data have been received
	  lcd_putcAtt   (  19*FW,   1*FH, sbuf[2], 0);				// satellites in view
        lcd_putsnAtt  (   2*FW,   2*FH, &rbuf[0][0], 2, APSIZE);		// hours
        lcd_putcAtt   (   6*FW,   2*FH, ':', DBLSIZE);			// ":"
        lcd_putsnAtt  (   8*FW,   2*FH, &rbuf[0][2], 2, APSIZE);		// minutes
        lcd_putcAtt   (  12*FW,   2*FH, ':', DBLSIZE);			// ":"
        lcd_putsnAtt  (  14*FW,   2*FH, &rbuf[0][4], 2, APSIZE);		// seconds
    }
    else
        lcd_putsAtt   (   2*FW,   2*FH, val_unknown, APSIZE);		// "?"

    if ((show_timer == 1) && rbuf[0][0])  {					// show the Timer when data have been received

        lcd_puts_P    (   2*FW,   4*FH, PSTR("Timer"));			// display "Timer"
        putsTime      (   5*FW,   5*FH, (gpstime-gpstimer), DBLSIZE, DBLSIZE);	// display difference as mm:ss
    }
    else
    {
        lcd_puts_P      ( 2*FW,   4*FH, PSTR("Date"));			// show the UTC Date	

        if (rbuf[1][0])	{
            lcd_putsnAtt( 2*FW,   5*FH, &rbuf[1][0], 2, APSIZE);		// year
            lcd_putcAtt ( 6*FW,   5*FH, '/', DBLSIZE);			// "/" 
            lcd_putsnAtt( 8*FW,   5*FH, &rbuf[1][2], 2, APSIZE);		// month
            lcd_putcAtt (12*FW,   5*FH, '/', DBLSIZE);			// "/"
            lcd_putsnAtt(14*FW,   5*FH, &rbuf[1][4], 2, APSIZE);		// day
        }
        else
            lcd_putsAtt   (   2*FW,   5*FH, val_unknown, APSIZE);		// "?"
    }
}
Пример #25
0
void menuTelemetryFrsky(uint8_t event)
{
  if (event == EVT_KEY_FIRST(KEY_EXIT)) {
    killEvents(event);
    chainMenu(menuMainView);
    return;
  }

  switch (event) {
    case EVT_KEY_BREAK(KEY_UP):
      if (s_frsky_view-- == 0)
        s_frsky_view = FRSKY_VIEW_MAX;
      break;

#if defined(PCBTARANIS)
    case EVT_KEY_BREAK(KEY_PAGE):
#endif
    case EVT_KEY_BREAK(KEY_DOWN):
      if (s_frsky_view++ == FRSKY_VIEW_MAX)
        s_frsky_view = 0;
      break;

#if defined(PCBTARANIS)
    case EVT_KEY_LONG(KEY_ENTER):
      killEvents(event);
      MENU_ADD_ITEM(STR_RESET_TELEMETRY);
      MENU_ADD_ITEM(STR_RESET_FLIGHT);
      menuHandler = onMainViewMenu;
      break;
#else
    case EVT_KEY_FIRST(KEY_ENTER):
      telemetryReset();
      break;
#endif
  }

  lcdDrawTelemetryTopBar();

  if (s_frsky_view < MAX_FRSKY_SCREENS) {
    FrSkyScreenData & screen = g_model.frsky.screens[s_frsky_view];
#if defined(GAUGES)
    if (g_model.frsky.screensType & (1<<s_frsky_view)) {
      // Custom Screen with gauges
      uint8_t barHeight = 5;
      for (int8_t i=3; i>=0; i--) {
        FrSkyBarData & bar = screen.bars[i];
        uint8_t source = bar.source;
        getvalue_t barMin = convertBarTelemValue(source, bar.barMin);
        getvalue_t barMax = convertBarTelemValue(source, 255-bar.barMax);
        if (source && barMax > barMin) {
          uint8_t y = barHeight+6+i*(barHeight+6);
          lcd_putsiAtt(0, y+barHeight-5, STR_VTELEMCHNS, source, 0);
          lcd_rect(25, y, BAR_WIDTH+1, barHeight+2);
          getvalue_t value = getValue(MIXSRC_FIRST_TELEM+source-1);
#if LCD_W >= 212
          putsTelemetryChannel(27+BAR_WIDTH, y+barHeight-6, source-1, value, LEFT);
#endif
          getvalue_t threshold = 0;
          uint8_t thresholdX = 0;
          if (source <= TELEM_TM2)
            threshold = 0;
          else if (source <= TELEM_RSSI_RX)
            threshold = getRssiAlarmValue(source-TELEM_RSSI_TX);
          else if (source <= TELEM_A2)
            threshold = g_model.frsky.channels[source-TELEM_A1].alarms_value[0];
#if defined(FRSKY_HUB)
          else
            threshold = convertBarTelemValue(source, barsThresholds[source-TELEM_ALT]);
#endif

          if (threshold) {
            thresholdX = barCoord(threshold, barMin, barMax);
            if (thresholdX == 100)
              thresholdX = 0;
          }

          uint8_t width = barCoord(value, barMin, barMax);

          // reversed barshade for T1/T2
          uint8_t barShade = ((threshold > value) ? DOTTED : SOLID);
          if (source == TELEM_T1 || source == TELEM_T2)
            barShade = -barShade;

          lcd_filled_rect(26, y+1, width, barHeight, barShade);

          for (uint8_t j=24; j<99; j+=25)
            if (j>thresholdX || j>width) lcd_vline(j*BAR_WIDTH/100+26, y+1, barHeight);

          if (thresholdX) {
            lcd_vlineStip(26+thresholdX, y-2, barHeight+3, DOTTED);
            lcd_hline(25+thresholdX, y-2, 3);
          }
        }
        else {
          barHeight += 2;
        }
      }
      displayRssiLine();
    }
    else
#endif
    {
      // Custom Screen with numbers
      uint8_t fields_count = 0;
      for (uint8_t i=0; i<4; i++) {
        for (uint8_t j=0; j<NUM_LINE_ITEMS; j++) {
          uint8_t field = screen.lines[i].sources[j];
          if (i==3 && j==0) {
#if LCD_W >= 212
            lcd_vline(69, 8, 48);
            lcd_vline(141, 8, 48);
#else
            lcd_vline(63, 8, 48);
#endif
            if (TELEMETRY_STREAMING()) {
#if defined(FRSKY_HUB)
              if (field == TELEM_ACC) {
                lcd_putsLeft(STATUS_BAR_Y, STR_ACCEL);
                lcd_outdezNAtt(4*FW, STATUS_BAR_Y, frskyData.hub.accelX, LEFT|PREC2);
                lcd_outdezNAtt(10*FW, STATUS_BAR_Y, frskyData.hub.accelY, LEFT|PREC2);
                lcd_outdezNAtt(16*FW, STATUS_BAR_Y, frskyData.hub.accelZ, LEFT|PREC2);
                break;
              }
#if defined(GPS)
              else if (field == TELEM_GPS_TIME) {
                displayGpsTime();
                return;
              }
#endif
#endif
            }
            else {
              displayRssiLine();
              return;
            }
          }
          if (field) {
            fields_count++;
            getvalue_t value = getValue(MIXSRC_FIRST_TELEM+field-1);
            uint8_t att = (i==3 ? NO_UNIT : DBLSIZE|NO_UNIT);
#if LCD_W >= 212
            xcoord_t pos[] = {0, 71, 143, 214};
#else
            xcoord_t pos[] = {0, 65, 130};
#endif
            putsTelemetryChannel(pos[j+1]-2, 1+FH+2*FH*i, field-1, value, att);
            
            if (field >= TELEM_TM1 && field <= TELEM_TM2 && i!=3) {
              // there is not enough space on LCD for displaying "Tmr1" or "Tmr2" and still see the - sign, we write "T1" or "T2" instead
              field = field-TELEM_TM1+TELEM_T1;
            }
            lcd_putsiAtt(pos[j], 1+FH+2*FH*i, STR_VTELEMCHNS, field, 0);
          }
        }
      }
      lcd_status_line();
      if (fields_count == 0)
        putEvent(event == EVT_KEY_BREAK(KEY_UP) ? event : EVT_KEY_BREAK(KEY_DOWN));
    }
  }
  else if (s_frsky_view == e_frsky_voltages) {
    // Volts / Amps / Watts / mAh
    uint8_t analog = 0;
#if defined(CPUARM)
    lcd_putsiAtt(0, 2*FH, STR_VOLTSRC, g_model.frsky.voltsSource, 0);
#else
    lcd_putsiAtt(0, 2*FH, STR_AMPSRC, g_model.frsky.voltsSource+1, 0);
#endif
    switch (g_model.frsky.voltsSource) {
#if defined(CPUARM)
      case FRSKY_VOLTS_SOURCE_RXBATT:
        putsTelemetryChannel(3*FW+6*FW+4, FH+1, TELEM_RXBATT-1, frskyData.analog[TELEM_ANA_RXBATT].value, DBLSIZE);
        break;
#endif
      case FRSKY_VOLTS_SOURCE_A1:
      case FRSKY_VOLTS_SOURCE_A2:
#if defined(CPUARM)
      case FRSKY_VOLTS_SOURCE_A3:
      case FRSKY_VOLTS_SOURCE_A4:
#endif
        displayVoltageScreenLine(2*FH, g_model.frsky.voltsSource);
        analog = 1+g_model.frsky.voltsSource;
        break;
#if defined(FRSKY_HUB)
      case FRSKY_VOLTS_SOURCE_FAS:
        putsTelemetryChannel(3*FW+6*FW+4, FH+1, TELEM_VFAS-1, frskyData.hub.vfas, DBLSIZE);
        break;
      case FRSKY_VOLTS_SOURCE_CELLS:
        putsTelemetryChannel(3*FW+6*FW+4, FH+1, TELEM_CELLS_SUM-1, frskyData.hub.cellsSum, DBLSIZE);
        break;
#endif
    }

    if (g_model.frsky.currentSource) {
      lcd_putsiAtt(0, 4*FH, STR_AMPSRC, g_model.frsky.currentSource, 0);
      switch(g_model.frsky.currentSource) {
        case FRSKY_CURRENT_SOURCE_A1:
        case FRSKY_CURRENT_SOURCE_A2:
#if defined(CPUARM)
        case FRSKY_CURRENT_SOURCE_A3:
        case FRSKY_CURRENT_SOURCE_A4:
#endif
          displayVoltageScreenLine(4*FH, g_model.frsky.currentSource-1);
          break;
#if defined(FRSKY_HUB)
        case FRSKY_CURRENT_SOURCE_FAS:
          putsTelemetryChannel(3*FW+6*FW+4, 3*FH+1, TELEM_CURRENT-1, frskyData.hub.current, DBLSIZE);
          break;
#endif
      }

      putsTelemetryChannel(4, 5*FH+1, TELEM_POWER-1, frskyData.hub.power, LEFT|DBLSIZE);
      putsTelemetryChannel(3*FW+4+4*FW+6*FW+FW, 5*FH+1, TELEM_CONSUMPTION-1, frskyData.hub.currentConsumption, DBLSIZE);
    }
    else {
      displayVoltageScreenLine(analog > 0 ? 5*FH : 4*FH, analog ? 2-analog : 0);
      if (analog == 0) displayVoltageScreenLine(6*FH, 1);
    }

#if defined(FRSKY_HUB)
    // Cells voltage
    if (frskyData.hub.cellsCount > 0) {
      uint8_t y = 1*FH;
      for (uint8_t k=0; k<frskyData.hub.cellsCount && k<6; k++) {
#if defined(GAUGES)
        uint8_t attr = (barsThresholds[THLD_CELL] && frskyData.hub.cellVolts[k] < barsThresholds[THLD_CELL]) ? BLINK|PREC2 : PREC2;
#else
        uint8_t attr = PREC2;
#endif
        lcd_outdezNAtt(LCD_W, y, TELEMETRY_CELL_VOLTAGE(k), attr, 4);
        y += 1*FH;
      }
#if defined(PCBTARANIS)      
      if (frskyData.hub.cellsCount > 6) {
        y = 1*FH;
        for (uint8_t k=6; k<frskyData.hub.cellsCount && k<12; k++) {
#if defined(GAUGES)
          uint8_t attr = (barsThresholds[THLD_CELL] && frskyData.hub.cellVolts[k] < barsThresholds[THLD_CELL]) ? BLINK|PREC2 : PREC2;
#else
          uint8_t attr = PREC2;
#endif
          lcd_outdezNAtt(LCD_W-3*FW-2, y, TELEMETRY_CELL_VOLTAGE(k), attr, 4);
          y += 1*FH;
        }
        lcd_vline(LCD_W-6*FW-4, 8, 47);       
      } else
#endif
      lcd_vline(LCD_W-3*FW-2, 8, 47);
    }
#endif

    displayRssiLine();
  }
#if defined(FRSKY_HUB)
  else if (s_frsky_view == e_frsky_after_flight) {
    uint8_t line=1*FH+1;
    if (IS_GPS_AVAILABLE()) {
      // Latitude
      lcd_putsLeft(line, STR_LATITUDE);
      displayGpsCoord(line, frskyData.hub.gpsLatitudeNS, frskyData.hub.gpsLatitude_bp, frskyData.hub.gpsLatitude_ap);
      // Longitude
      line+=1*FH+1;
      lcd_putsLeft(line, STR_LONGITUDE);
      displayGpsCoord(line, frskyData.hub.gpsLongitudeEW, frskyData.hub.gpsLongitude_bp, frskyData.hub.gpsLongitude_ap);
      displayGpsTime();
      line+=1*FH+1;
    }
    // Rssi
    lcd_putsLeft(line, STR_MINRSSI);
#if defined(PCBTARANIS)
    lcd_outdezNAtt(TELEM_2ND_COLUMN, line, frskyData.rssi[0].min, LEFT|LEADING0, 2);
#else
    lcd_puts(TELEM_2ND_COLUMN, line, STR_TX);
    lcd_outdezNAtt(TELEM_2ND_COLUMN+3*FW, line, frskyData.rssi[1].min, LEFT|LEADING0, 2);
    lcd_puts(TELEM_2ND_COLUMN+6*FW, line, STR_RX);
    lcd_outdezNAtt(TELEM_2ND_COLUMN+9*FW, line, frskyData.rssi[0].min, LEFT|LEADING0, 2);
#endif
  }
#endif    
}
Пример #26
0
void menuUp1(uint8_t event)
{
	FRESULT fr ;
	struct fileControl *fc = &FileControl ;
  static uint8_t mounted = 0 ;
	static uint32_t state ;
	static uint32_t firmwareAddress ;
	uint32_t i ;
	uint32_t width ;
	 
	if (UpdateItem == UPDATE_TYPE_BOOTLOADER )		// Bootloader
	{
  	TITLE( "UPDATE BOOT" ) ;
	}
	else
	{
#ifdef PCBX9D
		if (UpdateItem == UPDATE_TYPE_SPORT_INT )
		{
  		TITLE( "UPDATE Int. XJT" ) ;
		}
		else
		{
  		TITLE( "UPDATE Ext. SPort" ) ;
		}
#endif

#ifdef PCBSKY
 #ifndef REVX
 		if (UpdateItem == UPDATE_TYPE_COPROCESSOR )
		{
  		TITLE( "UPDATE COPROC" ) ;
		}
		else
		{
  		TITLE( "UPDATE SPort" ) ;
		}
 #else
 		if (UpdateItem == UPDATE_TYPE_SPORT_EXT )
		{
  		TITLE( "UPDATE SPort" ) ;
		}
 #endif
#endif
	}
	switch(event)
	{
    case EVT_ENTRY:
			state = UPDATE_NO_FILES ;
			if ( mounted == 0 )
			{
#if defined(PCBTARANIS)
  			fr = f_mount(0, &g_FATFS_Obj) ;
#else				
  			fr = f_mount(0, &g_FATFS) ;
#endif
#ifdef PCBX9D
				unlockFlash() ;
#endif
			}
			else
			{
				fr = FR_OK ;
			}
			if ( fr == FR_OK)
			{
				mounted = 1 ;
			}
			if ( mounted )
			{
				fr = f_chdir( (TCHAR *)"\\firmware" ) ;
				if ( fr == FR_OK )
				{
					state = UPDATE_NO_FILES ;
					fc->index = 0 ;
					fr = f_opendir( &Dj, (TCHAR *) "." ) ;
					if ( fr == FR_OK )
					{
 						if ( (UpdateItem > 1 ) )
						{
							fc->ext[0] = 'F' ;
							fc->ext[1] = 'R' ;
							fc->ext[2] = 'K' ;
						}
						else
						{
							fc->ext[0] = 'B' ;
							fc->ext[1] = 'I' ;
							fc->ext[2] = 'N' ;
						}
						fc->ext[3] = 0 ;
						fc->index = 0 ;
						fc->nameCount = fillNames( 0, fc ) ;
						fc->hpos = 0 ;
						fc->vpos = 0 ;
						if ( fc->nameCount )
						{
							state = UPDATE_FILE_LIST ;
						}
					}
				}
			}
    break ;
    
		case EVT_KEY_FIRST(KEY_EXIT):
			if ( state < UPDATE_ACTION )
			{
      	chainMenu(menuUpdate) ;
    		killEvents(event) ;
			}
    break ;
	}

	switch ( state )
	{
		case UPDATE_NO_FILES :
			lcd_puts_Pleft( 4*FH, "\005No Files" ) ;
	    lcd_outdez( 21*FW, 4*FH, mounted ) ;
    break ;
		
		case UPDATE_FILE_LIST :
			SportVerValid = 0 ;
			if ( fileList( event, &FileControl ) == 1 )
			{
				state = UPDATE_CONFIRM ;
			}
    break ;
		case UPDATE_CONFIRM :
 			if ( (UpdateItem > UPDATE_TYPE_BOOTLOADER ) )
			{
#ifdef PCBX9D
 				if ( (UpdateItem == UPDATE_TYPE_SPORT_INT ) )
				{
					lcd_puts_Pleft( 2*FH, "Flash Int. XJT from" ) ;
				}
				else
				{
					lcd_puts_Pleft( 2*FH, "Flash Ext.SP from" ) ;
				}
				SportVerValid = 0 ;
#else
 #ifndef REVX
 				if ( (UpdateItem == UPDATE_TYPE_COPROCESSOR ) )
				{
					lcd_puts_Pleft( 2*FH, "Flash Co-Proc. from" ) ;
				}
				else
				{
					lcd_puts_Pleft( 2*FH, "Flash SPort from" ) ;
				}
				CoProcReady = 0 ;
 #else
				lcd_puts_Pleft( 2*FH, "Flash SPort from" ) ;
 #endif
#endif
			}
			else
			{
				lcd_puts_Pleft( 2*FH, "Flash Bootloader from" ) ;
			}
			cpystr( cpystr( (uint8_t *)FlashFilename, (uint8_t *)"\\firmware\\" ), (uint8_t *)Filenames[fc->vpos] ) ;
#if defined(PCBTARANIS)
			lcd_putsnAtt( 0, 4*FH, Filenames[fc->vpos], DISPLAY_CHAR_WIDTH, 0 ) ;
#else
			lcd_putsnAtt0( 0, 4*FH, Filenames[fc->vpos], DISPLAY_CHAR_WIDTH, 0 ) ;
#endif
			if ( event == EVT_KEY_LONG(KEY_MENU) )
			{
				state = UPDATE_SELECTED ;
			}
			if ( event == EVT_KEY_LONG(KEY_EXIT) )
			{
				state = UPDATE_FILE_LIST ;		// Canceled
			}
    break ;
		case UPDATE_SELECTED :
			f_open( &FlashFile, FlashFilename, FA_READ ) ;
			f_read( &FlashFile, (BYTE *)FileData, 1024, &BlockCount ) ;
			i = 1 ;
			if (UpdateItem == UPDATE_TYPE_BOOTLOADER )		// Bootloader
			{
				i = validateFile( (uint32_t *) FileData ) ;
			}
			if ( i == 0 )
			{
				state = UPDATE_INVALID ;
			}
			else
			{
				if (UpdateItem == UPDATE_TYPE_BOOTLOADER )		// Bootloader
				{
#ifdef PCBX9D
					firmwareAddress = 0x08000000 ;
#endif
#ifdef PCBSKY
					firmwareAddress = 0x00400000 ;
#endif
				}
#ifdef PCBSKY
 #ifndef REVX
				else if (UpdateItem == UPDATE_TYPE_COPROCESSOR )		// Bootloader
				{
					firmwareAddress = 0x00000080 ;
					if ( check_ready() == 0 )
					{
						CoProcReady = 1 ;
					}
				}
 #endif
#endif
				else
				{
// SPort update
					SportState = SPORT_START ;
					FirmwareSize = FileSize[fc->vpos] ;
					BlockInUse = 0 ;
					f_read( &FlashFile, (BYTE *)ExtraFileData, 1024, &XblockCount ) ;
				}
				BytesFlashed = 0 ;
				BlockOffset = 0 ;
				ByteEnd = 1024 ;
				state = UPDATE_ACTION ;
			}
    break ;
		case UPDATE_INVALID :
			lcd_puts_Pleft( 2*FH, "Invalid File" ) ;
			lcd_puts_Pleft( 4*FH, "Press EXIT" ) ;
			if ( event == EVT_KEY_FIRST(KEY_EXIT) )
			{
				state = UPDATE_FILE_LIST ;		// Canceled
    		killEvents(event) ;
			}
    break ;
		case UPDATE_ACTION :
			// Do the flashing
			lcd_puts_Pleft( 3*FH, "Flashing" ) ;
			if (UpdateItem == UPDATE_TYPE_BOOTLOADER )		// Bootloader
			{
				width = ByteEnd >> 9 ;
				if ( BytesFlashed < ByteEnd )
				{
					program( (uint32_t *)firmwareAddress, &((uint32_t *)FileData)[BlockOffset] ) ;	// size is 256 bytes
					BlockOffset += 64 ;		// 32-bit words (256 bytes)
					firmwareAddress += 256 ;
					BytesFlashed += 256 ;
				}
				else
				{
					if ( ByteEnd >= 32768 )
					{
						state = UPDATE_COMPLETE ;
					}
					else
					{
						f_read( &FlashFile, (BYTE *)FileData, 1024, &BlockCount ) ;
						ByteEnd += 1024 ;
						BlockOffset = 0 ;
					}
				}
			}

#ifdef PCBSKY
 #ifndef REVX
			else if (UpdateItem == UPDATE_TYPE_COPROCESSOR )		// CoProcessor
Пример #27
0
void menuModelSelect(uint8_t event)
{
  if (s_warning_result) {
    s_warning_result = 0;
    eeDeleteModel(m_posVert); // delete file
    s_copyMode = 0;
    event = EVT_ENTRY_UP;
  }

  uint8_t _event_ = (IS_ROTARY_BREAK(event) || IS_ROTARY_LONG(event) ? 0 : event);

  if ((s_copyMode && EVT_KEY_MASK(event) == KEY_EXIT) || event == EVT_KEY_BREAK(KEY_EXIT)) {
    _event_ -= KEY_EXIT;
  }

  int8_t oldSub = m_posVert;

  check_submenu_simple(_event_, MAX_MODELS-1);

#if defined(NAVIGATION_POT2)
  if (event==0 && p2valdiff<0) {
    event = EVT_KEY_FIRST(KEY_RIGHT);
  }
#endif

  if (s_editMode > 0) s_editMode = 0;

#if !defined(CPUARM)
  if (event) {
    eeFlush(); // flush eeprom write
  }
#endif

  int8_t sub = m_posVert;

  switch (event)
  {
      case EVT_ENTRY:
        m_posVert = sub = g_eeGeneral.currModel;
        if (sub >= LCD_LINES-1) s_pgOfs = sub-LCD_LINES+2;
        s_copyMode = 0;
        s_editMode = EDIT_MODE_INIT;
        eeCheck(true);
        break;

      case EVT_KEY_LONG(KEY_EXIT):
        killEvents(event);
        if (s_copyMode && s_copyTgtOfs == 0 && g_eeGeneral.currModel != sub && eeModelExists(sub)) {
          POPUP_CONFIRMATION(STR_DELETEMODEL);
#if defined(CPUARM)
          SET_WARNING_INFO(modelHeaders[sub].name, sizeof(g_model.header.name), ZCHAR);
#else
          char * name = reusableBuffer.modelsel.mainname;
          eeLoadModelName(sub, name);
          SET_WARNING_INFO(name, sizeof(g_model.header.name), ZCHAR);
#endif
        }
        else {
          s_copyMode = 0;
          m_posVert = g_eeGeneral.currModel;
        }
        break;

#if defined(ROTARY_ENCODER_NAVIGATION)
      case EVT_ROTARY_LONG:
        killEvents(event);
        if (s_editMode < 0) {
          popMenu();
          break;
        }
        else if (!s_copyMode) {
          m_posVert = sub = g_eeGeneral.currModel;
          s_copyMode = 0;
          s_editMode = EDIT_MODE_INIT;
        }
        // no break
#endif

      case EVT_KEY_BREAK(KEY_EXIT):
        if (s_copyMode) {
          sub = m_posVert = (s_copyMode == MOVE_MODE || s_copySrcRow<0) ? (MAX_MODELS+sub+s_copyTgtOfs) % MAX_MODELS : s_copySrcRow;
          s_copyMode = 0;
        }
        else if (m_posVert != g_eeGeneral.currModel) {
          m_posVert = g_eeGeneral.currModel;
        }
        else {
          popMenu();
        }
        break;

#if defined(ROTARY_ENCODER_NAVIGATION)
      case EVT_ROTARY_BREAK:
        if (s_editMode == -1) {
          s_editMode = 0;
          break;
        }
        // no break;
#endif

      case EVT_KEY_LONG(KEY_ENTER):
      case EVT_KEY_BREAK(KEY_ENTER):
        s_editMode = 0;
        if (READ_ONLY()) {
          if (g_eeGeneral.currModel != sub && eeModelExists(sub)) {
            selectModel(sub);
          }
        }
        else if (s_copyMode && (s_copyTgtOfs || s_copySrcRow>=0)) {
          displayPopup(s_copyMode==COPY_MODE ? STR_COPYINGMODEL : STR_MOVINGMODEL);
          eeCheck(true); // force writing of current model data before this is changed

          uint8_t cur = (MAX_MODELS + sub + s_copyTgtOfs) % MAX_MODELS;

          if (s_copyMode == COPY_MODE) {
            if (!eeCopyModel(cur, s_copySrcRow)) {
              cur = sub;
            }
          }

          s_copySrcRow = g_eeGeneral.currModel; // to update the currModel value
          while (sub != cur) {
            uint8_t src = cur;
            cur = (s_copyTgtOfs > 0 ? cur+MAX_MODELS-1 : cur+1) % MAX_MODELS;
            eeSwapModels(src, cur);
            if (src == s_copySrcRow)
              s_copySrcRow = cur;
            else if (cur == s_copySrcRow)
              s_copySrcRow = src;
          }

          if (s_copySrcRow != g_eeGeneral.currModel) {
            g_eeGeneral.currModel = s_copySrcRow;
            eeDirty(EE_GENERAL);
          }

          s_copyMode = 0;
          event = EVT_ENTRY_UP;
        }
        else if (event == EVT_KEY_LONG(KEY_ENTER) || IS_ROTARY_BREAK(event)) {
          s_copyMode = 0;
          killEvents(event);
#if defined(NAVIGATION_MENUS)
          if (g_eeGeneral.currModel != sub) {
            if (eeModelExists(sub)) {
              MENU_ADD_ITEM(STR_SELECT_MODEL);
              MENU_ADD_SD_ITEM(STR_BACKUP_MODEL);
              MENU_ADD_ITEM(STR_COPY_MODEL);
              MENU_ADD_ITEM(STR_MOVE_MODEL);
              MENU_ADD_ITEM(STR_DELETE_MODEL);
            }
            else {
#if defined(SDCARD)
              MENU_ADD_ITEM(STR_CREATE_MODEL);
              MENU_ADD_ITEM(STR_RESTORE_MODEL);
#else
              selectModel(sub);
#endif
            }
          }
          else {
            MENU_ADD_SD_ITEM(STR_BACKUP_MODEL);
            MENU_ADD_ITEM(STR_COPY_MODEL);
            MENU_ADD_ITEM(STR_MOVE_MODEL);
          }
          menuHandler = onModelSelectMenu;
#else
          if (g_eeGeneral.currModel != sub) {
            selectModel(sub);
          }
#endif
        }
        else if (eeModelExists(sub)) {
          s_copyMode = (s_copyMode == COPY_MODE ? MOVE_MODE : COPY_MODE);
          s_copyTgtOfs = 0;
          s_copySrcRow = -1;
        }
        break;

#if defined(ROTARY_ENCODER_NAVIGATION)
      case EVT_ROTARY_LEFT:
      case EVT_ROTARY_RIGHT:
#endif
      case EVT_KEY_FIRST(KEY_LEFT):
      case EVT_KEY_FIRST(KEY_RIGHT):
#if defined(ROTARY_ENCODER_NAVIGATION)
        if ((!IS_ROTARY_RIGHT(event) && !IS_ROTARY_LEFT(event)) || s_editMode < 0) {
#endif
        if (sub == g_eeGeneral.currModel) {
          chainMenu((IS_ROTARY_RIGHT(event) || event == EVT_KEY_FIRST(KEY_RIGHT)) ? menuModelSetup : menuTabModel[DIM(menuTabModel)-1]);
        }
        else {
          AUDIO_WARNING2();
        }
        break;
#if defined(ROTARY_ENCODER_NAVIGATION)
        }
        // no break
#endif

      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) {
          int8_t next_ofs = s_copyTgtOfs + oldSub - m_posVert;
          if (next_ofs == MAX_MODELS || next_ofs == -MAX_MODELS)
            next_ofs = 0;

          if (s_copySrcRow < 0 && s_copyMode==COPY_MODE) {
            s_copySrcRow = oldSub;
            // find a hole (in the first empty slot above / below)
            sub = eeFindEmptyModel(s_copySrcRow, IS_ROTARY_DOWN(event) || event==EVT_KEY_FIRST(KEY_MOVE_DOWN));
            if (sub < 0) {
              // no free room for duplicating the model
              AUDIO_ERROR();
              sub = oldSub;
              s_copyMode = 0;
            }
            next_ofs = 0;
            m_posVert = sub;
          }
          s_copyTgtOfs = next_ofs;
        }
        break;
  }

#if !defined(PCBSKY9X)
  lcd_puts(9*FW-(LEN_FREE-4)*FW, 0, STR_FREE);
  if (event) reusableBuffer.modelsel.eepromfree = EeFsGetFree();
  lcd_outdezAtt(17*FW, 0, reusableBuffer.modelsel.eepromfree, 0);
#endif

#if defined(ROTARY_ENCODER_NAVIGATION)
  displayScreenIndex(e_ModelSelect, DIM(menuTabModel), (sub == g_eeGeneral.currModel) ? ((IS_RE_NAVIGATION_ENABLE() && s_editMode < 0) ? INVERS|BLINK : INVERS) : 0);
#else
  displayScreenIndex(e_ModelSelect, DIM(menuTabModel), (sub == g_eeGeneral.currModel) ? INVERS : 0);
#endif

  TITLE(STR_MENUMODELSEL);

  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;

    lcd_outdezNAtt(3*FW+2, y, k+1, LEADING0+((!s_copyMode && sub==k) ? INVERS : 0), 2);

    if (s_copyMode == MOVE_MODE || (s_copyMode == COPY_MODE && s_copySrcRow >= 0)) {
      if (k == sub) {
        if (s_copyMode == COPY_MODE) {
          k = s_copySrcRow;
          lcd_putc(MODELSEL_W-FW, y, '+');
        }
        else {
          k = sub + s_copyTgtOfs;
        }
      }
      else if (s_copyTgtOfs < 0 && ((k < sub && k >= sub+s_copyTgtOfs) || (k-MAX_MODELS < sub && k-MAX_MODELS >= sub+s_copyTgtOfs)))
        k += 1;
      else if (s_copyTgtOfs > 0 && ((k > sub && k <= sub+s_copyTgtOfs) || (k+MAX_MODELS > sub && k+MAX_MODELS <= sub+s_copyTgtOfs)))
        k += MAX_MODELS-1;
    }

    k %= MAX_MODELS;

    if (eeModelExists(k)) {
#if defined(PCBSKY9X)
      putsModelName(4*FW, y, modelHeaders[k].name, k, 0);
#else
      char * name = reusableBuffer.modelsel.listnames[i];
      if (event) eeLoadModelName(k, name);
      putsModelName(4*FW, y, name, k, 0);
      lcd_outdezAtt(20*FW, y, eeModelSize(k), 0);
#endif
      if (k==g_eeGeneral.currModel && (s_copyMode!=COPY_MODE || s_copySrcRow<0 || i+s_pgOfs!=(vertpos_t)sub))
        lcd_putc(1, y, '*');
    }

    if (s_copyMode && (vertpos_t)sub==i+s_pgOfs) {
      drawFilledRect(9, y, MODELSEL_W-1-9, 7);
      lcd_rect(8, y-1, MODELSEL_W-1-7, 9, s_copyMode == COPY_MODE ? SOLID : DOTTED);
    }
  }
}
Пример #28
0
void menuProcArduPilot1(uint8_t event)
{
    switch(event)						// new event received, branch accordingly
    {
    case EVT_KEY_FIRST(KEY_UP):
        chainMenu(menuProcArduPilot8);
        break;
    case EVT_KEY_FIRST(KEY_DOWN):
        chainMenu(menuProcArduPilot2);
        break;
    case EVT_KEY_FIRST(KEY_MENU):
        ARDUPILOT_DisableRXD();
        chainMenu(menuProcStatistic);
        break;
    case EVT_KEY_FIRST(KEY_EXIT):
        ARDUPILOT_DisableRXD();
        chainMenu(menuProc0);
        break;
    }
/*
    How to use: 

    You choose the values to be displayed using the function:

      initval(<number>, <packet>, <value>);
      -------------------------------------

    That means that "<value>" of "<packet>" is stored in the <number> buffer.
    The first <number> is 0.

    Here are the packet names and the associated value names:

    Position packet (beginning with "!!!"): "PACK_POS"
       value names: "LAT", "LON", "SPD", "CRT", "ALT", "ALH", "CRS", "BER",
       "WPN", "DST", "BTV", "RSP", "TOW"

    Attitude packet (beginning with "+++"): "PACK_ATT"
       value names: "ASP", "THH", "RLL", "PCH"

    Mode change packet (beginning with "###"): "PACK_MOD"
       value name: "MOD"

    Waypoint packet (beginning with "%%%"): "PACK_WPC"
       value name: "WPC"

    Alert packet (beginning with "XXX"): "PACK_ALR"
       value name: "ALR"

    Performance packet (beginning with "PPP"): "PACK_PRF"
       value name: "PRF"

    The buffers are accessed using the macro "VALSTR(<n>)", where "<n>" is "0"
    for the first buffer, and "1" for the second buffer.

    When a value is missing, it is replaced by the contents of val_unknown ("?").
*/
// expecting LAT value in POS packet to be stored in the first buffer
    initval (0, PACK_POS, LAT);
// and LON value in POS packet stored in the second buffer
    initval (1, PACK_POS, LON);
// title of the screen
    title ('1');
    lcd_puts_P  (5*FW, 1*FH, PSTR(" Latitude"));   // line 1 column 5
// first buffer into line 2 column 2
    lcd_putsAtt (2*FW, 2*FH, VALSTR(0), APSIZE);
    lcd_puts_P  (5*FW, 4*FH, PSTR(" Longitude"));  // line 4 column 5
// second buffer into line 5 column 2
    lcd_putsAtt (1*FW, 5*FH, VALSTR(1), APSIZE);
}
Пример #29
0
void menuStatisticsDebug(uint8_t event)
{
  TITLE(STR_MENUDEBUG);

  switch(event)
  {
    case EVT_KEY_LONG(KEY_ENTER):
      g_eeGeneral.mAhUsed = 0;
      g_eeGeneral.globalTimer = 0;
      eeDirty(EE_GENERAL);
      sessionTimer = 0;
      killEvents(event);
      AUDIO_KEYPAD_UP();
      break;
    case EVT_KEY_FIRST(KEY_ENTER):
#if defined(LUA)
      maxLuaInterval = 0;
      maxLuaDuration = 0;
#endif
      maxMixerDuration  = 0;
      AUDIO_KEYPAD_UP();
      break;

#if defined(DEBUG_TRACE_BUFFER)
    case EVT_KEY_FIRST(KEY_UP):
      pushMenu(menuTraceBuffer);
      return;
#endif

    case EVT_KEY_FIRST(KEY_DOWN):
      chainMenu(menuStatisticsView);
      break;
    case EVT_KEY_FIRST(KEY_EXIT):
      chainMenu(menuMainView);
      break;
  }

  lcd_putsLeft(MENU_DEBUG_Y_FREE_RAM, "Free Mem");
  lcd_outdezAtt(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_FREE_RAM, getAvailableMemory(), LEFT);
  lcd_puts(lcdLastPos, MENU_DEBUG_Y_FREE_RAM, "b");

#if defined(LUA)
  lcd_putsLeft(MENU_DEBUG_Y_LUA, "Lua scripts");
  lcd_putsAtt(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_LUA+1, "[Duration]", SMLSIZE);
  lcd_outdezAtt(lcdLastPos, MENU_DEBUG_Y_LUA, 10*maxLuaDuration, LEFT);
  lcd_putsAtt(lcdLastPos+2, MENU_DEBUG_Y_LUA+1, "[Interval]", SMLSIZE);
  lcd_outdezAtt(lcdLastPos, MENU_DEBUG_Y_LUA, 10*maxLuaInterval, LEFT);
#endif

  lcd_putsLeft(MENU_DEBUG_Y_MIXMAX, STR_TMIXMAXMS);
  lcd_outdezAtt(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_MIXMAX, DURATION_MS_PREC2(maxMixerDuration), PREC2|LEFT);
  lcd_puts(lcdLastPos, MENU_DEBUG_Y_MIXMAX, "ms");

  lcd_putsLeft(MENU_DEBUG_Y_RTOS, STR_FREESTACKMINB);
  lcd_putsAtt(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_RTOS+1, "[M]", SMLSIZE);
  lcd_outdezAtt(lcdLastPos, MENU_DEBUG_Y_RTOS, stack_free(0), UNSIGN|LEFT);
  lcd_putsAtt(lcdLastPos+2, MENU_DEBUG_Y_RTOS+1, "[X]", SMLSIZE);
  lcd_outdezAtt(lcdLastPos, MENU_DEBUG_Y_RTOS, stack_free(1), UNSIGN|LEFT);
  lcd_putsAtt(lcdLastPos+2, MENU_DEBUG_Y_RTOS+1, "[A]", SMLSIZE);
  lcd_outdezAtt(lcdLastPos, MENU_DEBUG_Y_RTOS, stack_free(2), UNSIGN|LEFT);
  lcd_putsAtt(lcdLastPos+2, MENU_DEBUG_Y_RTOS+1, "[I]", SMLSIZE);
  lcd_outdezAtt(lcdLastPos, MENU_DEBUG_Y_RTOS, stack_free(255), UNSIGN|LEFT);

  lcd_puts(3*FW, 7*FH+1, STR_MENUTORESET);
  lcd_status_line();
}
Пример #30
0
bool check(check_event_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t menuTabSize, const pm_uint8_t *horTab, uint8_t horTabMax, vertpos_t maxrow, uint8_t flags)
{
    vertpos_t l_posVert = m_posVert;
    horzpos_t l_posHorz = m_posHorz;

    uint8_t maxcol = MAXCOL(l_posVert);

#define scrollUD 0

    if (p2valdiff || scrollUD || p1valdiff) backlightOn(); // on keypress turn the light on

    if (menuTab) {
        uint8_t attr = 0;

        int8_t cc = curr;
        switch (event) {
        case EVT_KEY_LONG(KEY_MENU):
            if (menuTab == menuTabModel) {
                killEvents(event);
                if (modelHasNotes()) {
                    MENU_ADD_SD_ITEM(STR_VIEW_CHANNELS);
                    MENU_ADD_ITEM(STR_VIEW_NOTES);
                    menuHandler = onLongMenuPress;
                }
                else {
                    pushMenu(menuChannelsView);
                    return false;
                }
            }
            break;

        case EVT_KEY_LONG(KEY_PAGE):
            if (curr > 0)
                cc = curr - 1;
            else
                cc = menuTabSize-1;
            killEvents(event);
            break;

        case EVT_KEY_BREAK(KEY_PAGE):
            if (curr < (menuTabSize-1))
                cc = curr + 1;
            else
                cc = 0;
            break;
        }

        if (!calibrationState && cc != curr) {
            chainMenu((MenuFuncP)pgm_read_adr(&menuTab[cc]));
            return false;
        }

        if (!(flags&CHECK_FLAG_NO_SCREEN_INDEX)) {
            displayScreenIndex(curr, menuTabSize, attr);
        }

        lcd_filled_rect(0, 0, LCD_W, FH, SOLID, FILL_WHITE|GREY_DEFAULT);
    }

    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:
        menuEntryTime = get_tmr10ms();
        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

    case EVT_ENTRY_UP:
        menuEntryTime = get_tmr10ms();
        s_editMode = 0;
        l_posHorz = POS_HORZ_INIT(l_posVert);
        SET_SCROLLBAR_X(LCD_W-1);
        break;

    case EVT_ROTARY_BREAK:
        if (s_editMode > 1) break;
        if (m_posHorz < 0 && maxcol > 0 && READ_ONLY_UNLOCKED()) {
            l_posHorz = 0;
            break;
        }
        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();
        return false;

    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_posHorz >= 0 && (COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE)) {
            l_posHorz = -1;
        }
        else
        {
            uint8_t posVertInit = POS_VERT_INIT;
            if (s_pgOfs != 0 || l_posVert != posVertInit) {
                s_pgOfs = 0;
                l_posVert = posVertInit;
                l_posHorz = POS_HORZ_INIT(l_posVert);
            }
            else {
                popMenu();
                return false;
            }
        }
        break;

        CASE_EVT_ROTARY_MOVE_RIGHT
        if (s_editMode != 0) break;
        if ((COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE)) {
            if (l_posHorz >= 0) {
                INC(l_posHorz, 0, maxcol);
                break;
            }
        }
        else {
            if (l_posHorz < maxcol) {
                l_posHorz++;
                break;
            }
            else {
                l_posHorz = 0;
                if (!IS_ROTARY_MOVE_RIGHT(event))
                    break;
            }
        }

        do {
            INC(l_posVert, POS_VERT_INIT, maxrow);
        } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert));

        s_editMode = 0; // if we go down, we must be in this mode

        l_posHorz = POS_HORZ_INIT(l_posVert);
        break;

        CASE_EVT_ROTARY_MOVE_LEFT
        if (s_editMode != 0) break;
        if ((COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE)) {
            if (l_posHorz >= 0) {
                DEC(l_posHorz, 0, maxcol);
                break;
            }
        }
        else {
            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;
            }
        }

        do {
            DEC(l_posVert, POS_VERT_INIT, maxrow);
        } while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert));

        s_editMode = 0; // if we go up, we must be in this mode

        if ((COLATTR(l_posVert) & NAVIGATION_LINE_BY_LINE))
            l_posHorz = -1;
        else
            l_posHorz = min((uint8_t)l_posHorz, MAXCOL(l_posVert));

        break;
    }

#if defined(CPUARM)
    if (l_posVert<1) {
        s_pgOfs=0;
    }
    else if (menuTab && horTab) {
        if (maxrow > LCD_LINES-1) {
            while (1) {
                vertpos_t line = s_pgOfs+1;
                for (int numLines=0; line<=maxrow && numLines<LCD_LINES-1; line++) {
                    if (MAXCOL(line) != HIDDEN_ROW) {
                        numLines++;
                    }
                }
                int max = line - s_pgOfs - 1;
                if (l_posVert > max+s_pgOfs) {
                    s_pgOfs++;
                }
                else if (l_posVert < 1+s_pgOfs) {
                    s_pgOfs--;
                }
                else {
                    break;
                }
            }
        }
    }
    else {
        uint8_t max = menuTab ? LCD_LINES-1 : LCD_LINES-2;
        if (l_posVert>max+s_pgOfs) {
            s_pgOfs = l_posVert-max;
        }
        else if (l_posVert<1+s_pgOfs) {
            s_pgOfs = l_posVert-1;
        }
    }

#if LCD_W >= 212
    if (maxrow > LCD_LINES-1 && scrollbar_X)
        displayScrollbar(scrollbar_X, FH, LCD_H-FH, s_pgOfs, menuTab ? maxrow : maxrow+1, LCD_LINES-1);
#endif

#else
    uint8_t max = menuTab ? LCD_LINES-1 : LCD_LINES-2;
    if (l_posVert<1) s_pgOfs=0;
    else if (l_posVert>max+s_pgOfs) s_pgOfs = l_posVert-max;
    else if (l_posVert<1+s_pgOfs) s_pgOfs = l_posVert-1;
#endif
    m_posVert = l_posVert;
    m_posHorz = l_posHorz;
    if (s_pgOfs > 0) {
        l_posVert--;
        if (l_posVert == s_pgOfs && CURSOR_NOT_ALLOWED_IN_ROW(l_posVert)) {
            s_pgOfs = l_posVert-1;
        }
    }
    return true;
}