/* * Authors (alphabetical order) * - Andre Bernet * - Andreas Weitl * - Bertrand Songis * - Bryan J. Rentoul (Gruvin) * - Cameron Weeks * - Erez Raviv * - Gabriel Birkus * - Jean-Pierre Parisy * - Karl Szmutny * - Michael Blandford * - Michal Hlavinka * - Pat Mackenzie * - Philip Moss * - Rob Thomson * - Romolo Manfredini * - Thomas Husterer * * opentx is based on code named * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, * er9x by Erez Raviv: http://code.google.com/p/er9x/, * and the original (and ongoing) project by * Thomas Husterer, th9x: http://code.google.com/p/th9x/ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ #ifndef menus_h #define menus_h #define NO_HI_LEN 25 void displayScreenIndex(uint8_t index, uint8_t count, uint8_t attr); inline void displayColumnHeader(const char **headers, uint8_t index) { lcd_putsAtt(17*FW, 0, headers[index], 0); } #if !defined(CPUM64) void displayScrollbar(xcoord_t x, uint8_t y, uint8_t h, uint16_t offset, uint16_t count, uint8_t visible); #endif #if LCD_W >= 212 extern uint8_t scrollbar_X; #define SET_SCROLLBAR_X(x) scrollbar_X = (x); #else #define SET_SCROLLBAR_X(x) #endif #if LCD_W >= 212 #if defined(TRANSLATIONS_FR) #define MENU_COLUMNS 1 #define COLUMN_X 0 #else #define MENU_COLUMNS 2 #endif #define MENUS_SCROLLBAR_WIDTH 2 #define MENU_COLUMN2_X (8 + LCD_W / 2) #define lcd_putsColumnLeft(x, y, str) lcd_puts((x > (LCD_W-10*FW-MENUS_SCROLLBAR_WIDTH)) ? MENU_COLUMN2_X : 0, y, str) #else #define MENUS_SCROLLBAR_WIDTH 0 #define MENU_COLUMNS 1 #define COLUMN_X 0 #define lcd_putsColumnLeft(x, y, str) lcd_putsLeft(y, str) #endif // Menus related stuff ... #if defined(SDCARD) typedef uint16_t vertpos_t; #else typedef uint8_t vertpos_t; #endif #if defined(PCBTARANIS) typedef uint8_t & check_event_t; #define horzpos_t int8_t #else typedef uint8_t check_event_t; #define horzpos_t uint8_t #endif extern vertpos_t m_posVert; extern horzpos_t m_posHorz; extern vertpos_t s_pgOfs; extern uint8_t s_noHi; extern uint8_t s_noScroll; void menu_lcd_onoff(uint8_t x, uint8_t y, uint8_t value, LcdFlags attr); typedef void (*MenuFuncP)(uint8_t event); typedef void (*MenuFuncP_PROGMEM)(uint8_t event); extern const MenuFuncP_PROGMEM menuTabModel[]; extern MenuFuncP g_menuStack[5]; extern uint8_t g_menuStackPtr; /// goto given Menu, but substitute current menu in menuStack void chainMenu(MenuFuncP newMenu); /// goto given Menu, store current menu in menuStack void pushMenu(MenuFuncP newMenu); /// return to last menu in menustack void popMenu(); ///deliver address of last menu which was popped from inline MenuFuncP lastPopMenu() { return g_menuStack[g_menuStackPtr+1]; } void drawPotsBars(); void doMainScreenGraphics(); void menuFirstCalib(uint8_t event); void onMainViewMenu(const char *result); void menuMainView(uint8_t event); void menuGeneralDiagAna(uint8_t event); #if defined(FRSKY) void menuTelemetryFrsky(uint8_t event); #endif void menuGeneralSetup(uint8_t event); void menuGeneralCalib(uint8_t event); void menuModelSelect(uint8_t event); void menuModelCustomFunctions(uint8_t event); void menuStatisticsView(uint8_t event); void menuStatisticsDebug(uint8_t event); void menuAboutView(uint8_t event); #if defined(NAVIGATION_POT1) extern int16_t p1valdiff; #else #define p1valdiff 0 #endif #if defined(NAVIGATION_POT2) extern int8_t p2valdiff; #else #define p2valdiff 0 #endif extern int8_t checkIncDec_Ret; // global helper vars #define EDIT_SELECT_MENU -1 #define EDIT_SELECT_FIELD 0 #define EDIT_MODIFY_FIELD 1 #define EDIT_MODIFY_STRING 2 extern int8_t s_editMode; // global editmode // checkIncDec flags #define EE_GENERAL 0x01 #define EE_MODEL 0x02 #define NO_INCDEC_MARKS 0x04 #define INCDEC_SWITCH 0x08 #define INCDEC_SOURCE 0x10 #define DBLKEYS_1000 0x20 // mawrow special values #define TITLE_ROW ((uint8_t)-1) #define HIDDEN_ROW ((uint8_t)-2) #if defined(CPUARM) typedef bool (*IsValueAvailable)(int16_t); int16_t checkIncDec(uint8_t event, int16_t i_pval, int16_t i_min, int16_t i_max, uint8_t i_flags=0, IsValueAvailable isValueAvailable=NULL); #else int16_t checkIncDec(uint8_t event, int16_t i_pval, int16_t i_min, int16_t i_max, uint8_t i_flags=0); #endif #if defined(CPUM64) int8_t checkIncDecModel(uint8_t event, int8_t i_val, int8_t i_min, int8_t i_max); int8_t checkIncDecModelZero(uint8_t event, int8_t i_val, int8_t i_max); int8_t checkIncDecGen(uint8_t event, int8_t i_val, int8_t i_min, int8_t i_max); #else #define checkIncDecModel(event, i_val, i_min, i_max) checkIncDec(event, i_val, i_min, i_max, EE_MODEL) #define checkIncDecModelZero(event, i_val, i_max) checkIncDec(event, i_val, 0, i_max, EE_MODEL) #define checkIncDecGen(event, i_val, i_min, i_max) checkIncDec(event, i_val, i_min, i_max, EE_GENERAL) #endif #define CHECK_INCDEC_MODELVAR(event, var, min, max) \ var = checkIncDecModel(event,var,min,max) #define CHECK_INCDEC_MODELVAR_ZERO(event, var, max) \ var = checkIncDecModelZero(event,var,max) #if defined(CPUARM) bool isSwitchAvailable(int16_t swtch); #define AUTOSWITCH_ENTER_LONG() (attr && event==EVT_KEY_LONG(KEY_ENTER)) #define CHECK_INCDEC_MODELSWITCH(event, var, min, max) \ var = checkIncDec(event,var,min,max,EE_MODEL|INCDEC_SWITCH|NO_INCDEC_MARKS, isSwitchAvailable) #elif defined(AUTOSWITCH) #define AUTOSWITCH_ENTER_LONG() (attr && event==EVT_KEY_LONG(KEY_ENTER)) #define CHECK_INCDEC_MODELSWITCH(event, var, min, max) \ var = checkIncDec(event,var,min,max,EE_MODEL|INCDEC_SWITCH) #else #define AUTOSWITCH_ENTER_LONG() (0) #define CHECK_INCDEC_MODELSWITCH CHECK_INCDEC_MODELVAR #endif #if defined(CPUARM) bool isSourceAvailable(int16_t source); bool isInputSourceAvailable(int16_t source); #define CHECK_INCDEC_MODELSOURCE(event, var, min, max) \ var = checkIncDec(event,var,min,max,EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isSourceAvailable) #elif defined(AUTOSOURCE) #define CHECK_INCDEC_MODELSOURCE(event, var, min, max) \ var = checkIncDec(event,var,min,max,EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS) #else #define CHECK_INCDEC_MODELSOURCE CHECK_INCDEC_MODELVAR #endif #define CHECK_INCDEC_GENVAR(event, var, min, max) \ var = checkIncDecGen(event,var,min,max) #if defined(PCBTARANIS) #define NAVIGATION_LINE_BY_LINE 0x40 #else #define NAVIGATION_LINE_BY_LINE 0 #endif bool check(check_event_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t menuTabSize, const pm_uint8_t *subTab, uint8_t subTabMax, vertpos_t maxrow); bool check_simple(check_event_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t menuTabSize, vertpos_t maxrow); bool check_submenu_simple(check_event_t event, uint8_t maxrow); void title(const pm_char * s); #define TITLE(str) title(str) #if defined(CPUARM) #define MENU_TAB(...) const uint8_t mstate_tab[] = __VA_ARGS__ #else #define MENU_TAB(...) static const pm_uint8_t mstate_tab[] PROGMEM = __VA_ARGS__ #endif #define MENU_CHECK(tab, menu, lines_count) \ check(event, menu, tab, DIM(tab), mstate_tab, DIM(mstate_tab)-1, (lines_count)-1) #define MENU(title, tab, menu, lines_count, ...) \ MENU_TAB(__VA_ARGS__); \ if (!MENU_CHECK(tab, menu, lines_count)) return; \ TITLE(title) #define SIMPLE_MENU_NOTITLE(tab, menu, lines_count) \ if (!check_simple(event,menu,tab,DIM(tab),(lines_count)-1)) return; #define SIMPLE_MENU(title, tab, menu, lines_count) \ SIMPLE_MENU_NOTITLE(tab, menu, lines_count); \ TITLE(title) #define SUBMENU_NOTITLE(lines_count, ...) { \ MENU_TAB(__VA_ARGS__); \ if (!check(event,0,NULL,0,mstate_tab,DIM(mstate_tab)-1,(lines_count)-1)) return; } #define SUBMENU(title, lines_count, ...) \ MENU_TAB(__VA_ARGS__); \ if (!check(event,0,NULL,0,mstate_tab,DIM(mstate_tab)-1,(lines_count)-1)) return; \ TITLE(title) #define SIMPLE_SUBMENU_NOTITLE(lines_count) \ if (!check_submenu_simple(event,(lines_count)-1)) return; #define SIMPLE_SUBMENU(title, lines_count) \ SIMPLE_SUBMENU_NOTITLE(lines_count); \ TITLE(title) #if defined(CPUARM) typedef int select_menu_value_t; #else typedef int8_t select_menu_value_t; #endif select_menu_value_t selectMenuItem(uint8_t x, uint8_t y, const pm_char *label, const pm_char *values, select_menu_value_t value, select_menu_value_t min, select_menu_value_t max, LcdFlags attr, uint8_t event); uint8_t onoffMenuItem(uint8_t value, uint8_t x, uint8_t y, const pm_char *label, LcdFlags attr, uint8_t event ); int8_t switchMenuItem(uint8_t x, uint8_t y, int8_t value, LcdFlags attr, uint8_t event); #if defined(CPUARM) && defined(GVARS) #define GVAR_MENU_ITEM(x, y, v, min, max, lcdattr, editflags, event) gvarMenuItem(x, y, v, min, max, lcdattr, editflags, event) #else #define GVAR_MENU_ITEM(x, y, v, min, max, lcdattr, editflags, event) gvarMenuItem(x, y, v, min, max, lcdattr, event) #endif #if defined(GVARS) #if defined(CPUARM) int16_t gvarMenuItem(uint8_t x, uint8_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t editflags, uint8_t event); #else int16_t gvarMenuItem(uint8_t x, uint8_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event); // @@@ open.20.fsguruh #endif #define displayGVar(x, y, v, min, max) GVAR_MENU_ITEM(x, y, v, min, max, 0, 0, 0) #else int8_t gvarMenuItem(uint8_t x, uint8_t y, int8_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event); #define displayGVar(x, y, v, min, max) lcd_outdez8(x, y, v) #endif #define WARNING_TYPE_ASTERISK 0 #define WARNING_TYPE_CONFIRM 1 #define WARNING_TYPE_INPUT 2 extern const pm_char * s_warning; extern const pm_char * s_warning_info; extern uint8_t s_warning_info_len; extern uint8_t s_warning_result; extern uint8_t s_warning_type; extern const pm_char * s_global_warning; #define WARNING_LINE_X 16 #define WARNING_LINE_Y 3*FH #if LCD_W >= 212 #define WARNING_LINE_LEN 30 #else #define WARNING_LINE_LEN 20 #endif void displayBox(); void displayPopup(const pm_char * pstr); void displayWarning(uint8_t event); #if defined(CPUARM) extern void (*popupFunc)(uint8_t event); extern int16_t s_warning_input_value; extern int16_t s_warning_input_min; extern int16_t s_warning_input_max; #endif #if defined(CPUARM) #define DISPLAY_WARNING (*popupFunc) #define POPUP_WARNING(s) (s_warning = s, popupFunc = displayWarning) #define POPUP_CONFIRMATION(s) (s_warning = s, s_warning_type = WARNING_TYPE_CONFIRM, popupFunc = displayWarning) #define POPUP_INPUT(s, func, start, min, max) (s_warning = s, s_warning_type = WARNING_TYPE_INPUT, popupFunc = func, s_warning_input_value = start, s_warning_input_min = min, s_warning_input_max = max) #else #define DISPLAY_WARNING displayWarning #define POPUP_WARNING(s) s_warning = s #define POPUP_CONFIRMATION(s) (s_warning = s, s_warning_type = WARNING_TYPE_CONFIRM) #endif #if defined(SDCARD) || (defined(ROTARY_ENCODER_NAVIGATION) && !defined(CPUM64)) #define NAVIGATION_MENUS #define MENU_ADD_ITEM(s) s_menu[s_menu_count++] = s #define MENU_MAX_LINES 6 #if defined(SDCARD) #define MENU_ADD_SD_ITEM(s) MENU_ADD_ITEM(s) #else #define MENU_ADD_SD_ITEM(s) #endif #define MENU_LINE_LENGTH (LEN_MODEL_NAME+1) extern const char *s_menu[MENU_MAX_LINES]; extern uint16_t s_menu_count; extern uint8_t s_menu_flags; extern uint16_t s_menu_offset; const char * displayMenu(uint8_t event); extern void (*menuHandler)(const char *result); #else #define s_menu_count 0 #endif #if defined(SDCARD) #define STATUS_LINE_LENGTH 32 extern char statusLineMsg[STATUS_LINE_LENGTH]; void showStatusLine(); void drawStatusLine(); #else #define drawStatusLine() #endif #if defined(PCBTARANIS) void menuChannelsView(uint8_t event); void pushMenuTextView(const char *filename); #endif #define LABEL(...) (uint8_t)-1 #if defined(PCBTARANIS) #define KEY_MOVE_UP KEY_PLUS #define KEY_MOVE_DOWN KEY_MINUS #define CURSOR_MOVED_LEFT(event) (EVT_KEY_MASK(event) == KEY_PLUS) #define CURSOR_MOVED_RIGHT(event) (EVT_KEY_MASK(event) == KEY_MINUS) #define CASE_EVT_ROTARY_MOVE_RIGHT CASE_EVT_ROTARY_LEFT #define CASE_EVT_ROTARY_MOVE_LEFT CASE_EVT_ROTARY_RIGHT #define IS_ROTARY_MOVE_RIGHT IS_ROTARY_LEFT #define IS_ROTARY_MOVE_LEFT IS_ROTARY_RIGHT #else #define KEY_MOVE_UP KEY_UP #define KEY_MOVE_DOWN KEY_DOWN #define CURSOR_MOVED_LEFT(event) (IS_ROTARY_LEFT(event) || EVT_KEY_MASK(event) == KEY_LEFT) #define CURSOR_MOVED_RIGHT(event) (IS_ROTARY_RIGHT(event) || EVT_KEY_MASK(event) == KEY_RIGHT) #define CASE_EVT_ROTARY_MOVE_RIGHT CASE_EVT_ROTARY_RIGHT #define CASE_EVT_ROTARY_MOVE_LEFT CASE_EVT_ROTARY_LEFT #define IS_ROTARY_MOVE_RIGHT IS_ROTARY_RIGHT #define IS_ROTARY_MOVE_LEFT IS_ROTARY_LEFT #endif #if defined(PCBTARANIS) #define REPEAT_LAST_CURSOR_MOVE() { if (CURSOR_MOVED_LEFT(event) || CURSOR_MOVED_RIGHT(event)) putEvent(event); else m_posHorz = 0; } #define MOVE_CURSOR_FROM_HERE() if (m_posHorz > 0) REPEAT_LAST_CURSOR_MOVE() #elif defined(ROTARY_ENCODER_NAVIGATION) #define REPEAT_LAST_CURSOR_MOVE() { if (EVT_KEY_MASK(event) >= 0x0e) putEvent(event); else m_posHorz = 0; } #define MOVE_CURSOR_FROM_HERE() if (m_posHorz > 0) REPEAT_LAST_CURSOR_MOVE() #else #define REPEAT_LAST_CURSOR_MOVE() m_posHorz = 0; #define MOVE_CURSOR_FROM_HERE() REPEAT_LAST_CURSOR_MOVE() #endif #if defined(PCBTARANIS) #define POS_VERT_INIT (menuTab ? (MAXCOL((uint16_t)1) == 255 ? 2 : 1) : 0) #define POS_HORZ_INIT(posVert) ((COLATTR(posVert) & NAVIGATION_LINE_BY_LINE) ? -1 : 0) #define EDIT_MODE_INIT 0 // TODO enum #else #define POS_VERT_INIT 0 #define POS_HORZ_INIT(posVert) 0 #define EDIT_MODE_INIT -1 #endif #endif