From acd974403b6724c06e810b66b2eccc645dceea40 Mon Sep 17 00:00:00 2001 From: "Tim G. Foley" Date: Thu, 16 Jan 2014 18:06:34 -0800 Subject: [PATCH] Fixed cross initialization error --- .gitignore | 7 + radio/src/gui/menu_model.cpp~ | 5643 --------------------------- radio/src/telemetry/frsky.cpp | 3 +- radio/src/telemetry/frsky.cpp~ | 926 ----- radio/src/telemetry/frsky_sport.cpp | 12 +- 5 files changed, 20 insertions(+), 6571 deletions(-) create mode 100644 .gitignore delete mode 100644 radio/src/gui/menu_model.cpp~ delete mode 100644 radio/src/telemetry/frsky.cpp~ diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..4b4d86a64 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*.[oa] +*~ +opentx.bin +opentx.elf +opentx.lst +opentx.map + diff --git a/radio/src/gui/menu_model.cpp~ b/radio/src/gui/menu_model.cpp~ deleted file mode 100644 index d1f9889fb..000000000 --- a/radio/src/gui/menu_model.cpp~ +++ /dev/null @@ -1,5643 +0,0 @@ -/* - * 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. - * - */ - -#include "../opentx.h" -#ifdef MAVLINK -#include "gui/view_mavlink.h" -#endif - -#define WCHART 32 -#define X0 (LCD_W-WCHART-2) -#define Y0 32 - -enum EnumTabModel { - e_ModelSelect, - e_ModelSetup, - IF_HELI(e_Heli) - IF_FLIGHT_MODES(e_FlightModesAll) - e_InputsAll, - e_MixAll, - e_Limits, - IF_CURVES(e_CurvesAll) -#if LCD_W >= 212 - IF_GVARS(e_GVars) -#endif - e_CustomSwitches, - e_CustomFunctions, -#if defined(LUA_MODEL_SCRIPTS) - e_CustomScripts, -#endif - IF_FRSKY(e_Telemetry) - IF_MAVLINK(e_MavSetup) - IF_TEMPLATES(e_Templates) -}; - -void menuModelSelect(uint8_t event); -void menuModelSetup(uint8_t event); -void menuModelHeli(uint8_t event); -void menuModelFlightModesAll(uint8_t event); -void menuModelExposAll(uint8_t event); -void menuModelMixAll(uint8_t event); -void menuModelLimits(uint8_t event); -void menuModelCurvesAll(uint8_t event); -void menuModelGVars(uint8_t event); -void menuModelCustomSwitches(uint8_t event); -void menuModelCustomFunctions(uint8_t event); -void menuModelCustomScripts(uint8_t event); -void menuModelTelemetry(uint8_t event); -void menuModelTemplates(uint8_t event); -void menuModelExpoOne(uint8_t event); - -const MenuFuncP_PROGMEM menuTabModel[] PROGMEM = { - menuModelSelect, - menuModelSetup, - IF_HELI(menuModelHeli) - IF_FLIGHT_MODES(menuModelFlightModesAll) - menuModelExposAll, - menuModelMixAll, - menuModelLimits, - IF_CURVES(menuModelCurvesAll) -#if LCD_W >= 212 && defined(GVARS) && defined(FLIGHT_MODES) - IF_GVARS(menuModelGVars) -#endif - menuModelCustomSwitches, - menuModelCustomFunctions, -#if defined(LUA_MODEL_SCRIPTS) - menuModelCustomScripts, -#endif - IF_FRSKY(menuModelTelemetry) - IF_MAVLINK(menuTelemetryMavlinkSetup) - IF_TEMPLATES(menuModelTemplates) -}; - -#define COPY_MODE 1 -#define MOVE_MODE 2 -static uint8_t s_copyMode = 0; -static int8_t s_copySrcRow; -static int8_t s_copyTgtOfs; - -uint8_t eeFindEmptyModel(uint8_t id, bool down) -{ - uint8_t i = id; - for (;;) { - i = (MAX_MODELS + (down ? i+1 : i-1)) % MAX_MODELS; - if (!eeModelExists(i)) break; - if (i == id) return 0xff; // no free space in directory left - } - return i; -} - -void selectModel(uint8_t sub) -{ - displayPopup(STR_LOADINGMODEL); - saveTimers(); - eeCheck(true); // force writing of current model data before this is changed - g_eeGeneral.currModel = sub; - eeDirty(EE_GENERAL); - eeLoadModel(sub); -} - -#if defined(SDCARD) -#define LIST_NONE_SD_FILE 1 -bool listSdFiles(const char *path, const char *extension, const uint8_t maxlen, const char *selection, uint8_t flags=0) -{ - FILINFO fno; - DIR dir; - char *fn; /* This function is assuming non-Unicode cfg. */ -#if _USE_LFN - TCHAR lfn[_MAX_LFN + 1]; - fno.lfname = lfn; - fno.lfsize = sizeof(lfn); -#endif - - static uint16_t s_last_menu_offset = 0; - -#if defined(CPUARM) - static uint8_t s_last_flags; - - if (selection) { - s_last_flags = flags; - memset(reusableBuffer.modelsel.menu_bss, 0, sizeof(reusableBuffer.modelsel.menu_bss)); - strcpy(reusableBuffer.modelsel.menu_bss[0], path); - strcat(reusableBuffer.modelsel.menu_bss[0], "/"); - strncat(reusableBuffer.modelsel.menu_bss[0], selection, maxlen); - strcat(reusableBuffer.modelsel.menu_bss[0], extension); - if (f_stat(reusableBuffer.modelsel.menu_bss[0], &fno) != FR_OK) { - selection = NULL; - } - } - else { - flags = s_last_flags; - } -#endif - - if (s_menu_offset == 0) { - s_last_menu_offset = 0; - memset(reusableBuffer.modelsel.menu_bss, 0, sizeof(reusableBuffer.modelsel.menu_bss)); - } - else if (s_menu_offset == s_menu_count - MENU_MAX_LINES) { - s_last_menu_offset = 0xffff; - memset(reusableBuffer.modelsel.menu_bss, 0, sizeof(reusableBuffer.modelsel.menu_bss)); - } - else if (s_menu_offset == s_last_menu_offset) { - // should not happen, only there because of Murphy's law - return true; - } - else if (s_menu_offset > s_last_menu_offset) { - memmove(reusableBuffer.modelsel.menu_bss[0], reusableBuffer.modelsel.menu_bss[1], (MENU_MAX_LINES-1)*MENU_LINE_LENGTH); - memset(reusableBuffer.modelsel.menu_bss[MENU_MAX_LINES-1], 0xff, MENU_LINE_LENGTH); - } - else { - memmove(reusableBuffer.modelsel.menu_bss[1], reusableBuffer.modelsel.menu_bss[0], (MENU_MAX_LINES-1)*MENU_LINE_LENGTH); - memset(reusableBuffer.modelsel.menu_bss[0], 0, MENU_LINE_LENGTH); - } - - s_menu_count = 0; - s_menu_flags = BSS; - - FRESULT res = f_opendir(&dir, path); /* Open the directory */ - if (res == FR_OK) { - - if (flags & LIST_NONE_SD_FILE) { - s_menu_count++; - if (selection) { - s_last_menu_offset++; - } - else if (s_menu_offset==0 || s_menu_offset < s_last_menu_offset) { - char *line = reusableBuffer.modelsel.menu_bss[0]; - memset(line, 0, MENU_LINE_LENGTH); - strcpy(line, "---"); - s_menu[0] = line; - } - } - - for (;;) { - res = f_readdir(&dir, &fno); /* Read a directory item */ - if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */ - -#if _USE_LFN - fn = *fno.lfname ? fno.lfname : fno.fname; -#else - fn = fno.fname; -#endif - - uint8_t len = strlen(fn); - if (len < 5 || len > maxlen+4 || strcasecmp(fn+len-4, extension) || (fno.fattrib & AM_DIR)) continue; - - s_menu_count++; - fn[len-4] = '\0'; - - if (s_menu_offset == 0) { - if (selection && strncasecmp(fn, selection, maxlen) < 0) { - s_last_menu_offset++; - } - else { - for (uint8_t i=0; i=0; i--) { - char *line = reusableBuffer.modelsel.menu_bss[i]; - if (line[0] == '\0' || strcasecmp(fn, line) > 0) { - if (i > 0) memmove(reusableBuffer.modelsel.menu_bss[0], reusableBuffer.modelsel.menu_bss[1], sizeof(reusableBuffer.modelsel.menu_bss[i]) * i); - memset(line, 0, MENU_LINE_LENGTH); - strcpy(line, fn); - break; - } - } - for (uint8_t i=0; i s_last_menu_offset) { - if (strcasecmp(fn, reusableBuffer.modelsel.menu_bss[MENU_MAX_LINES-2]) > 0 && strcasecmp(fn, reusableBuffer.modelsel.menu_bss[MENU_MAX_LINES-1]) < 0) { - memset(reusableBuffer.modelsel.menu_bss[MENU_MAX_LINES-1], 0, MENU_LINE_LENGTH); - strcpy(reusableBuffer.modelsel.menu_bss[MENU_MAX_LINES-1], fn); - } - } - else { - if (strcasecmp(fn, reusableBuffer.modelsel.menu_bss[1]) < 0 && strcasecmp(fn, reusableBuffer.modelsel.menu_bss[0]) > 0) { - memset(reusableBuffer.modelsel.menu_bss[0], 0, MENU_LINE_LENGTH); - strcpy(reusableBuffer.modelsel.menu_bss[0], fn); - } - } - } - } - - if (s_menu_offset > 0) - s_last_menu_offset = s_menu_offset; - else - s_menu_offset = s_last_menu_offset; - - return s_menu_count; -} -#endif - -#if defined(PCBTARANIS) - static int8_t modelselBitmapIdx; - static uint8_t modelselBitmap[MODEL_BITMAP_SIZE]; - #define MODELSEL_W 133 - #define BMP_DIRTY() modelselBitmapIdx = -1 -#else - #define MODELSEL_W LCD_W - #define BMP_DIRTY() -#endif - -#if defined(NAVIGATION_MENUS) -void onModelSelectMenu(const char *result) -{ - int8_t sub = m_posVert; - - if (result == STR_SELECT_MODEL || result == STR_CREATE_MODEL) { - selectModel(sub); - } - else if (result == STR_COPY_MODEL) { - s_copyMode = COPY_MODE; - s_copyTgtOfs = 0; - s_copySrcRow = -1; - } - else if (result == STR_MOVE_MODEL) { - s_copyMode = MOVE_MODE; - s_copyTgtOfs = 0; - s_copySrcRow = -1; - } -#if defined(SDCARD) - else if (result == STR_BACKUP_MODEL) { - eeCheck(true); // force writing of current model data before this is changed - POPUP_WARNING(eeBackupModel(sub)); - } - else if (result == STR_RESTORE_MODEL || result == STR_UPDATE_LIST) { - if (!listSdFiles(MODELS_PATH, MODELS_EXT, sizeof(g_model.header.name), NULL)) { - POPUP_WARNING(STR_NO_MODELS_ON_SD); - s_menu_flags = 0; - } - } -#endif - else if (result == STR_DELETE_MODEL) { - POPUP_CONFIRMATION(STR_DELETEMODEL); -#if defined(CPUARM) - s_warning_info = modelHeaders[sub].name; -#else - char * name = reusableBuffer.modelsel.mainname; - eeLoadModelName(sub, name); - s_warning_info = name; -#endif - s_warning_info_len = sizeof(g_model.header.name); - } -#if defined(SDCARD) - else { - // The user choosed a file on SD to restore - POPUP_WARNING(eeRestoreModel(sub, (char *)result)); - BMP_DIRTY(); - if (!s_warning && g_eeGeneral.currModel == sub) - eeLoadModel(sub); - } -#endif -} -#endif - -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; - BMP_DIRTY(); - } - - uint8_t _event_ = (IS_ROTARY_BREAK(event) || IS_ROTARY_LONG(event) ? 0 : event); - -#if defined(PCBTARANIS) - if ((s_copyMode && EVT_KEY_MASK(event) == KEY_EXIT) || event == EVT_KEY_BREAK(KEY_EXIT)) - _event_ -= KEY_EXIT; -#else - if (s_copyMode && EVT_KEY_MASK(event) == KEY_EXIT) - _event_ -= KEY_EXIT; -#endif - - int8_t oldSub = m_posVert; - - if (!check_submenu_simple(_event_, MAX_MODELS-1)) return; - -#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; - BMP_DIRTY(); - eeCheck(true); - break; - case EVT_KEY_LONG(KEY_EXIT): - if (s_copyMode && s_copyTgtOfs == 0 && g_eeGeneral.currModel != sub && eeModelExists(sub)) { - POPUP_CONFIRMATION(STR_DELETEMODEL); -#if defined(CPUARM) - s_warning_info = modelHeaders[sub].name; -#else - char * name = reusableBuffer.modelsel.mainname; - eeLoadModelName(sub, name); - s_warning_info = name; -#endif - s_warning_info_len = sizeof(g_model.header.name); - killEvents(event); - break; - } - // no break -#if defined(ROTARY_ENCODER_NAVIGATION) - case EVT_ROTARY_LONG: - killEvents(event); - if (s_editMode < 0) { - popMenu(); - return; - } - 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; - } -#if defined(PCBTARANIS) - else { - if (m_posVert != g_eeGeneral.currModel) { - m_posVert = g_eeGeneral.currModel; - s_pgOfs = 0; - } - else { - popMenu(); - return; - } - } -#endif - 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)) - BMP_DIRTY(); - else - 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); - BMP_DIRTY(); - 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) -#if !defined(PCBTARANIS) - || IS_ROTARY_BREAK(event) -#endif - ) { - 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(PCBTARANIS) - case EVT_KEY_BREAK(KEY_PAGE): - case EVT_KEY_LONG(KEY_PAGE): - chainMenu(event == EVT_KEY_BREAK(KEY_PAGE) ? menuModelSetup : menuTabModel[DIM(menuTabModel)-1]); - killEvents(event); - return; -#else -#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]); - return; - } - AUDIO_WARNING2(); - break; -#if defined(ROTARY_ENCODER_NAVIGATION) - } - // no break -#endif -#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(PCBTARANIS) - lcd_puts(27*FW-(LEN_FREE-4)*FW, 0, STR_FREE); - if (event) reusableBuffer.modelsel.eepromfree = EeFsGetFree(); - lcd_outdezAtt(20*FW, 0, reusableBuffer.modelsel.eepromfree, 0); - lcd_puts(21*FW, 0, STR_BYTES); -#elif !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); -#elif defined(PCBTARANIS) - displayScreenIndex(e_ModelSelect, DIM(menuTabModel), 0); - lcd_filled_rect(0, 0, LCD_W, FH, SOLID, FILL_WHITE|GREY_DEFAULT); -#else - displayScreenIndex(e_ModelSelect, DIM(menuTabModel), (sub == g_eeGeneral.currModel) ? INVERS : 0); -#endif - - TITLE(STR_MENUMODELSEL); - - for (uint8_t i=0; i= 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); -#elif defined(CPUARM) - putsModelName(4*FW, y, modelHeaders[k].name, k, 0); - lcd_outdezAtt(20*FW, y, eeModelSize(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) { - lcd_filled_rect(9, y, MODELSEL_W-1-9, 7); - lcd_rect(8, y-1, MODELSEL_W-1-7, 9, s_copyMode == COPY_MODE ? SOLID : DOTTED); - } - } - -#if defined(PCBTARANIS) - if (modelselBitmapIdx != m_posVert) { - modelselBitmapIdx = m_posVert; - if (modelselBitmapIdx == g_eeGeneral.currModel) - memcpy(modelselBitmap, modelBitmap, MODEL_BITMAP_SIZE); - else - loadModelBitmap(modelHeaders[sub].bitmap, modelselBitmap); - } - lcd_bmp(22*FW+2, 2*FH+FH/2, modelselBitmap); -#endif -} - -#if defined(PCBTARANIS) -uint8_t g_moduleIdx; -void menuModelFailsafe(uint8_t event) -{ - static bool longNames = false; - bool newLongNames = false; - uint8_t ch; - - if (event == EVT_KEY_BREAK(KEY_ENTER) && s_editMode) { - g_model.moduleData[g_moduleIdx].failsafeChannels[m_posVert] = channelOutputs[m_posVert]; - eeDirty(EE_MODEL); - AUDIO_WARNING1(); - SEND_FAILSAFE_NOW(g_moduleIdx); - } - - SIMPLE_SUBMENU_NOTITLE(32); - - SET_SCROLLBAR_X(0); - - if (m_posVert >= 16) - ch = 16; - else - ch = 0; - - lcd_putsCenter(0*FH, FAILSAFESET); - lcd_invert_line(0); - - // Column separator - lcd_vline(LCD_W/2, FH, LCD_H-FH); - - for (uint8_t col=0; col<2; col++) { - - uint8_t x = col*LCD_W/2+1; - - // Channels - for (uint8_t line=0; line<8; line++) { - uint8_t y = 9+line*7; - int32_t val; - uint8_t ofs = (col ? 0 : 1); - - if (ch < g_model.moduleData[g_moduleIdx].channelsStart || ch >= NUM_CHANNELS(g_moduleIdx) + g_model.moduleData[g_moduleIdx].channelsStart) - val = 0; - else if (s_editMode && m_posVert == ch) - val = channelOutputs[ch]; - else - val = g_model.moduleData[g_moduleIdx].failsafeChannels[8*col+line]; - - // Channel name if present, number if not - uint8_t lenLabel = ZLEN(g_model.limitData[ch].name); - if (lenLabel > 4) { - newLongNames = longNames = true; - } - - if (lenLabel > 0) - lcd_putsnAtt(x+1-ofs, y, g_model.limitData[ch].name, sizeof(g_model.limitData[ch].name), ZCHAR | SMLSIZE); - else - putsChn(x+1-ofs, y, ch+1, SMLSIZE); - - // Value - LcdFlags flags = TINSIZE; - if (m_posVert == ch) { - flags |= INVERS; - if (s_editMode) - flags |= BLINK; - } -#if defined(PPM_UNIT_US) - uint8_t wbar = (longNames ? 54 : 64); - lcd_outdezAtt(x+LCD_W/2-4-wbar-ofs, y, PPM_CH_CENTER(ch)+val/2, flags); -#elif defined(PPM_UNIT_PERCENT_PREC1) - uint8_t wbar = (longNames ? 48 : 58); - lcd_outdezAtt(x+LCD_W/2-4-wbar-ofs, y, calcRESXto1000(val), PREC1|flags); -#else - uint8_t wbar = (longNames ? 54 : 64); - lcd_outdezAtt(x+LCD_W/2-4-wbar-ofs, y, calcRESXto1000(val)/10, flags); -#endif - - // Gauge - lcd_rect(x+LCD_W/2-3-wbar-ofs, y, wbar+1, 6); - uint16_t lim = g_model.extendedLimits ? 640*2 : 512*2; - uint8_t len = limit((uint8_t)1, uint8_t((abs(val) * wbar/2 + lim/2) / lim), uint8_t(wbar/2)); - uint8_t x0 = (val>0) ? x+LCD_W/2-ofs-3-wbar/2 : x+LCD_W/2-ofs-2-wbar/2-len; - lcd_hline(x0, y+1, len); - lcd_hline(x0, y+2, len); - lcd_hline(x0, y+3, len); - lcd_hline(x0, y+4, len); - - ch++; - } - } - - longNames = newLongNames; -} -#endif - -#if defined(CPUM64) - #define editNameCursorPos m_posHorz -#else - static uint8_t editNameCursorPos = 0; -#endif - -void editName(uint8_t x, uint8_t y, char *name, uint8_t size, uint8_t event, uint8_t active) -{ -#if defined(CPUM64) - // in order to save flash - lcd_putsLeft(y, STR_NAME); -#endif - - lcd_putsnAtt(x, y, name, size, ZCHAR | ((active && s_editMode <= 0) ? INVERS : 0)); - - if (active) { - uint8_t cur = editNameCursorPos; - if (s_editMode > 0) { - int8_t c = name[cur]; - int8_t v = c; - - if (p1valdiff || IS_ROTARY_RIGHT(event) || IS_ROTARY_LEFT(event) || event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_FIRST(KEY_UP) - || event==EVT_KEY_REPT(KEY_DOWN) || event==EVT_KEY_REPT(KEY_UP)) { - v = checkIncDec(event, abs(v), 0, LEN_STD_CHARS, 0); - if (c <= 0) v = -v; - } - - switch (event) { -#if defined(ROTARY_ENCODER_NAVIGATION) || defined(PCBTARANIS) - case EVT_ROTARY_BREAK: - if (s_editMode == EDIT_MODIFY_FIELD) { - s_editMode = EDIT_MODIFY_STRING; - cur = 0; - } - else if (cur0) cur--; - break; - case EVT_KEY_BREAK(KEY_RIGHT): - if (cur=-26 && v<=26) { - v = -v; // toggle case - if (event==EVT_KEY_LONG(KEY_LEFT)) - killEvents(KEY_LEFT); - } - break; - } - - if (c != v) { - name[cur] = v; - eeDirty(EE_MODEL); - } - lcd_putcAtt(x+editNameCursorPos*FW, y, idx2char(v), INVERS); - } - else { - cur = 0; - } - editNameCursorPos = cur; - } -} - -#if defined(CPUM64) -#define editSingleName(x, y, label, name, size, event, active) editName(x, y, name, size, event, active) -#else -void editSingleName(uint8_t x, uint8_t y, const pm_char *label, char *name, uint8_t size, uint8_t event, uint8_t active) -{ - lcd_putsLeft(y, label); - editName(x, y, name, size, event, active); -} -#endif - -enum menuModelSetupItems { - ITEM_MODEL_NAME, - CASE_PCBTARANIS(ITEM_MODEL_BITMAP) - ITEM_MODEL_TIMER1, - IF_PERSISTENT_TIMERS(ITEM_MODEL_TIMER1_PERSISTENT) - ITEM_MODEL_TIMER1_MINUTE_BEEP, - ITEM_MODEL_TIMER1_COUNTDOWN_BEEP, - ITEM_MODEL_TIMER2, - IF_PERSISTENT_TIMERS(ITEM_MODEL_TIMER2_PERSISTENT) - ITEM_MODEL_TIMER2_MINUTE_BEEP, - ITEM_MODEL_TIMER2_COUNTDOWN_BEEP, - ITEM_MODEL_EXTENDED_LIMITS, - ITEM_MODEL_EXTENDED_TRIMS, - ITEM_MODEL_TRIM_INC, - ITEM_MODEL_THROTTLE_REVERSED, - ITEM_MODEL_THROTTLE_TRACE, - ITEM_MODEL_THROTTLE_TRIM, - ITEM_MODEL_THROTTLE_WARNING, - ITEM_MODEL_SWITCHES_WARNING, - ITEM_MODEL_BEEP_CENTER, -#if defined(PCBTARANIS) - ITEM_MODEL_INTERNAL_MODULE_LABEL, - ITEM_MODEL_INTERNAL_MODULE_MODE, - ITEM_MODEL_INTERNAL_MODULE_CHANNELS, - ITEM_MODEL_INTERNAL_MODULE_BIND, - ITEM_MODEL_INTERNAL_MODULE_FAILSAFE, - ITEM_MODEL_EXTERNAL_MODULE_LABEL, - ITEM_MODEL_EXTERNAL_MODULE_MODE, - ITEM_MODEL_EXTERNAL_MODULE_CHANNELS, - ITEM_MODEL_EXTERNAL_MODULE_BIND, - ITEM_MODEL_EXTERNAL_MODULE_FAILSAFE, - ITEM_MODEL_TRAINER_LABEL, - ITEM_MODEL_TRAINER_MODE, - ITEM_MODEL_TRAINER_CHANNELS, - ITEM_MODEL_TRAINER_SETTINGS, -#elif defined(PCBSKY9X) - ITEM_MODEL_PPM1_PROTOCOL, - ITEM_MODEL_PPM1_PARAMS, - ITEM_MODEL_PPM2_PROTOCOL, - ITEM_MODEL_PPM2_PARAMS, -#else - ITEM_MODEL_PPM1_PROTOCOL, - ITEM_MODEL_PPM1_PARAMS, -#endif - ITEM_MODEL_SETUP_MAX -}; - -#if defined(PCBSKY9X) - #define FIELD_PROTOCOL_MAX 2 -#else - #define FIELD_PROTOCOL_MAX 1 -#endif - -#if LCD_W >= 212 -#define MODEL_SETUP_2ND_COLUMN (LCD_W-17*FW-MENUS_SCROLLBAR_WIDTH) -#else -#define MODEL_SETUP_2ND_COLUMN (LCD_W-11*FW-MENUS_SCROLLBAR_WIDTH) -#endif - -#if defined(PCBTARANIS) && defined(SDCARD) -void copySelection(char *dst, const char *src, uint8_t size) -{ - if (memcmp(src, "---", 3) == 0) - memset(dst, 0, size); - else - memcpy(dst, src, size); -} - -void onModelSetupBitmapMenu(const char *result) -{ - if (result == STR_UPDATE_LIST) { - if (!listSdFiles(BITMAPS_PATH, BITMAPS_EXT, sizeof(g_model.header.bitmap), NULL)) { - POPUP_WARNING(STR_NO_BITMAPS_ON_SD); - s_menu_flags = 0; - } - } - else { - // The user choosed a bmp file in the list - copySelection(g_model.header.bitmap, result, sizeof(g_model.header.bitmap)); - LOAD_MODEL_BITMAP(); - memcpy(modelHeaders[g_eeGeneral.currModel].bitmap, g_model.header.bitmap, sizeof(g_model.header.bitmap)); - eeDirty(EE_MODEL); - } -} -#endif - -void menuModelSetup(uint8_t event) -{ -#if defined(PCBTARANIS) - #define IF_PORT1_ON(x) (g_model.moduleData[0].rfProtocol == RF_PROTO_OFF ? HIDDEN_ROW : (uint8_t)(x)) - #define IF_PORT2_ON(x) (g_model.externalModule == MODULE_TYPE_NONE ? HIDDEN_ROW : (uint8_t)(x)) - #define IF_TRAINER_ON(x) (g_model.trainerMode ? (uint8_t)(x) : HIDDEN_ROW) - #define IF_PORT_ON(idx, x) (idx==0 ? IS_PORT1_ON(x) : (idx==1 ? IS_PORT2_ON(x) : IS_TRAINER_ON())) - #define IF_PORT2_XJT(x) (IS_MODULE_XJT(1) ? (uint8_t)x : HIDDEN_ROW) - #define IS_D8_RX(x) (g_model.moduleData[x].rfProtocol == RF_PROTO_D8) - #define PORT1_CHANNELS_ROWS() IF_PORT1_ON(1) - #define PORT2_CHANNELS_ROWS() IF_PORT2_ON(IS_MODULE_DSM2(1) ? (uint8_t)0 : (uint8_t)1) - #define TRAINER_CHANNELS_ROWS() IF_TRAINER_ON(1) - #define PORT_CHANNELS_ROWS(x) (x==0 ? PORT1_CHANNELS_ROWS() : (x==1 ? PORT2_CHANNELS_ROWS() : TRAINER_CHANNELS_ROWS())) - #define FAILSAFE_ROWS(x) ((g_model.moduleData[x].rfProtocol==RF_PROTO_X16 || g_model.moduleData[x].rfProtocol==RF_PROTO_LR12) ? (g_model.moduleData[x].failsafeMode==FAILSAFE_CUSTOM ? (uint8_t)1 : (uint8_t)0) : HIDDEN_ROW) - #define MODEL_SETUP_MAX_LINES (1+ITEM_MODEL_SETUP_MAX) - - bool CURSOR_ON_CELL = (m_posHorz >= 0); - MENU_TAB({ 0, 0, CASE_PCBTARANIS(0) 2, IF_PERSISTENT_TIMERS(0) 0, 0, 2, IF_PERSISTENT_TIMERS(0) 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, NAVIGATION_LINE_BY_LINE|(NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1), LABEL(InternalModule), 0, IF_PORT1_ON(1), IF_PORT1_ON(IS_D8_RX(0) ? (uint8_t)1 : (uint8_t)2), IF_PORT1_ON(FAILSAFE_ROWS(0)), LABEL(ExternalModule), (g_model.externalModule==MODULE_TYPE_XJT || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0, PORT2_CHANNELS_ROWS(), (IS_MODULE_XJT(1) && IS_D8_RX(1)) ? (uint8_t)1 : (IS_MODULE_PPM(1) || IS_MODULE_XJT(1) || IS_MODULE_DSM2(1)) ? (uint8_t)2 : HIDDEN_ROW, IF_PORT2_XJT(FAILSAFE_ROWS(1)), LABEL(Trainer), 0, TRAINER_CHANNELS_ROWS(), IF_TRAINER_ON(2)}); -#elif defined(CPUM64) - #define CURSOR_ON_CELL (true) - #define MODEL_SETUP_MAX_LINES ((IS_PPM_PROTOCOL(protocol)||IS_DSM2_PROTOCOL(protocol)||IS_PXX_PROTOCOL(protocol)) ? 1+ITEM_MODEL_SETUP_MAX : ITEM_MODEL_SETUP_MAX) - - uint8_t protocol = g_model.protocol; - MENU_TAB({ 0, 0, CASE_PCBTARANIS(0) 2, IF_PERSISTENT_TIMERS(0) 0, 0, 2, IF_PERSISTENT_TIMERS(0) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1, FIELD_PROTOCOL_MAX, 2 }); -#else - #define CURSOR_ON_CELL (true) - #define MODEL_SETUP_MAX_LINES ((IS_PPM_PROTOCOL(protocol)||IS_DSM2_PROTOCOL(protocol)||IS_PXX_PROTOCOL(protocol)) ? 1+ITEM_MODEL_SETUP_MAX : ITEM_MODEL_SETUP_MAX) - - uint8_t protocol = g_model.protocol; - MENU_TAB({ 0, 0, CASE_PCBTARANIS(0) 2, IF_PERSISTENT_TIMERS(0) 0, 0, 2, IF_PERSISTENT_TIMERS(0) 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1, FIELD_PROTOCOL_MAX, 2, IF_PCBSKY9X(1) IF_PCBSKY9X(2) }); -#endif - - if (!MENU_CHECK(menuTabModel, e_ModelSetup, MODEL_SETUP_MAX_LINES)) { -#if defined(DSM2) - dsm2Flag = 0; -#endif -#if defined(PCBTARANIS) - pxxFlag[INTERNAL_MODULE] = 0; - pxxFlag[EXTERNAL_MODULE] = 0; -#endif - return; - } - - TITLE(STR_MENUSETUP); - - uint8_t sub = m_posVert - 1; - int8_t editMode = s_editMode; - - for (uint8_t i=0; i0) ? BLINK|INVERS : INVERS); - uint8_t attr = (sub == k ? blink : 0); - - switch(k) { - case ITEM_MODEL_NAME: - editSingleName(MODEL_SETUP_2ND_COLUMN, y, STR_MODELNAME, g_model.header.name, sizeof(g_model.header.name), event, attr); -#if defined(CPUARM) - memcpy(modelHeaders[g_eeGeneral.currModel].name, g_model.header.name, sizeof(g_model.header.name)); -#endif - break; - -#if defined(PCBTARANIS) && defined(SDCARD) - case ITEM_MODEL_BITMAP: - lcd_putsLeft(y, STR_BITMAP); - if (ZEXIST(g_model.header.bitmap)) - lcd_putsnAtt(MODEL_SETUP_2ND_COLUMN, y, g_model.header.bitmap, sizeof(g_model.header.bitmap), attr); - else - lcd_putsiAtt(MODEL_SETUP_2ND_COLUMN, y, STR_VCSWFUNC, 0, attr); - if (attr && event==EVT_KEY_BREAK(KEY_ENTER) && READ_ONLY_UNLOCKED()) { - s_editMode = 0; - if (listSdFiles(BITMAPS_PATH, BITMAPS_EXT, sizeof(g_model.header.bitmap), g_model.header.bitmap, LIST_NONE_SD_FILE)) { - menuHandler = onModelSetupBitmapMenu; - } - else { - POPUP_WARNING(STR_NO_BITMAPS_ON_SD); - s_menu_flags = 0; - } - } - break; -#endif - - case ITEM_MODEL_TIMER1: - case ITEM_MODEL_TIMER2: - case ITEM_MODEL_TIMER1_MINUTE_BEEP: - case ITEM_MODEL_TIMER2_MINUTE_BEEP: - case ITEM_MODEL_TIMER1_COUNTDOWN_BEEP: - case ITEM_MODEL_TIMER2_COUNTDOWN_BEEP: - { - TimerData *timer = &g_model.timers[k>=ITEM_MODEL_TIMER2 ? 1 : 0]; - if (k==ITEM_MODEL_TIMER1_MINUTE_BEEP || k==ITEM_MODEL_TIMER2_MINUTE_BEEP) { - timer->minuteBeep = onoffMenuItem(timer->minuteBeep, MODEL_SETUP_2ND_COLUMN, y, STR_MINUTEBEEP, attr, event); - } - else if (k==ITEM_MODEL_TIMER1_COUNTDOWN_BEEP || k==ITEM_MODEL_TIMER2_COUNTDOWN_BEEP) { -#if defined(CPUARM) - timer->countdownBeep = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_BEEPCOUNTDOWN, STR_VBEEPCOUNTDOWN, timer->countdownBeep, 0, 2, attr, event); -#else - timer->countdownBeep = onoffMenuItem(timer->countdownBeep, MODEL_SETUP_2ND_COLUMN, y, STR_BEEPCOUNTDOWN, attr, event); -#endif - } - else { - putsStrIdx(0*FW, y, STR_TIMER, k>=ITEM_MODEL_TIMER2 ? 2 : 1); - putsTmrMode(MODEL_SETUP_2ND_COLUMN, y, timer->mode, m_posHorz==0 ? attr : 0); - putsTime(MODEL_SETUP_2ND_COLUMN+5*FW-2+5*FWNUM+1, y, timer->start, m_posHorz==1 ? attr : 0, m_posHorz==2 ? attr : 0); -#if defined(PCBTARANIS) - if (attr && m_posHorz < 0) lcd_filled_rect(MODEL_SETUP_2ND_COLUMN, y, LCD_W-MODEL_SETUP_2ND_COLUMN-MENUS_SCROLLBAR_WIDTH, 8); -#endif - if (attr && (editMode>0 || p1valdiff)) { - div_t qr = div(timer->start, 60); - switch (m_posHorz) { - case 0: - CHECK_INCDEC_MODELVAR(event, timer->mode, -2*(MAX_PSWITCH+NUM_CSW), TMR_VAROFS-1+2*(MAX_PSWITCH+NUM_CSW)); - break; - case 1: - CHECK_INCDEC_MODELVAR_ZERO(event, qr.quot, 59); - timer->start = qr.rem + qr.quot*60; - break; - case 2: - qr.rem -= checkIncDecModel(event, qr.rem+2, 1, 62)-2; - timer->start -= qr.rem ; - if ((int16_t)timer->start < 0) timer->start=0; - break; - } - } - } - break; - } - -#if defined(CPUARM) || defined(PCBGRUVIN9X) - case ITEM_MODEL_TIMER1_PERSISTENT: - case ITEM_MODEL_TIMER2_PERSISTENT: - { - TimerData &timer = g_model.timers[k==ITEM_MODEL_TIMER2_PERSISTENT]; - timer.persistent = onoffMenuItem(timer.persistent, MODEL_SETUP_2ND_COLUMN, y, STR_PERSISTENT, attr, event); - break; - } -#endif - - case ITEM_MODEL_EXTENDED_LIMITS: - g_model.extendedLimits = onoffMenuItem(g_model.extendedLimits, MODEL_SETUP_2ND_COLUMN, y, STR_ELIMITS, attr, event); - break; - - case ITEM_MODEL_EXTENDED_TRIMS: -#if defined(CPUM64) - g_model.extendedTrims = onoffMenuItem(g_model.extendedTrims, MODEL_SETUP_2ND_COLUMN, y, STR_ETRIMS, attr, event); -#else - g_model.extendedTrims = onoffMenuItem(g_model.extendedTrims, MODEL_SETUP_2ND_COLUMN, y, STR_ETRIMS, m_posHorz<=0 ? attr : 0, event==EVT_KEY_BREAK(KEY_ENTER) ? event : 0); - lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_RESET_BTN, m_posHorz>0 ? attr : 0); - if (attr && m_posHorz>0) { - s_editMode = 0; - if (event==EVT_KEY_LONG(KEY_ENTER)) { - for (uint8_t i=0; i MIXSRC_Thr) - idx += 1; - if (idx >= MIXSRC_FIRST_POT+NUM_POTS) - idx += MIXSRC_CH1 - MIXSRC_FIRST_POT - NUM_POTS; - putsMixerSource(MODEL_SETUP_2ND_COLUMN, y, idx, attr); - break; - } - - case ITEM_MODEL_THROTTLE_TRIM: - g_model.thrTrim = onoffMenuItem(g_model.thrTrim, MODEL_SETUP_2ND_COLUMN, y, STR_TTRIM, attr, event); - break; - - case ITEM_MODEL_THROTTLE_WARNING: - g_model.disableThrottleWarning = !onoffMenuItem(!g_model.disableThrottleWarning, MODEL_SETUP_2ND_COLUMN, y, STR_THROTTLEWARNING, attr, event); - break; - - case ITEM_MODEL_SWITCHES_WARNING: - { - lcd_putsLeft(y, STR_SWITCHWARNING); - swstate_t states = g_model.switchWarningStates; - char c = !(states & 1); - menu_lcd_onoff(MODEL_SETUP_2ND_COLUMN, y, c, attr); - if (attr) { - s_editMode = 0; - switch(event) { - case EVT_KEY_LONG(KEY_ENTER): - if (!READ_ONLY()) { - killEvents(event); - getMovedSwitch(); - g_model.switchWarningStates = 0x01 + (switches_states << 1); - } - // no break - CASE_EVT_ROTARY_BREAK - case EVT_KEY_BREAK(KEY_ENTER): -#if !defined(PCBTARANIS) - case EVT_KEY_BREAK(KEY_LEFT): - case EVT_KEY_BREAK(KEY_RIGHT): -#endif - if (!READ_ONLY()) { - g_model.switchWarningStates ^= 0x01; - eeDirty(EE_MODEL); - } - break; - } - } - if (c) { - states >>= 1; - for (uint8_t i=1; i>= 2; -#else - attr = 0; - if (IS_3POS(i-1)) { - c = '0'+(states & 0x03); - states >>= 2; - } - else { - if (states & 0x01) - attr = INVERS; - c = pgm_read_byte(STR_VSWITCHES - 2 + 6 + (3*i)); - states >>= 1; - } - lcd_putcAtt(MODEL_SETUP_2ND_COLUMN+2*FW+i*FW, y, c, attr); -#endif - } - } - break; - } - - case ITEM_MODEL_BEEP_CENTER: - lcd_putsLeft(y, STR_BEEPCTR); - for (uint8_t i=0; i0 || p1valdiff)) { - switch (m_posHorz) { - case 0: - CHECK_INCDEC_MODELVAR(event, g_model.externalModule, MODULE_TYPE_NONE, MODULE_TYPE_COUNT-1); - if (checkIncDec_Ret) { - g_model.moduleData[EXTERNAL_MODULE].channelsStart = 0; - if (g_model.externalModule == MODULE_TYPE_PPM) - g_model.moduleData[EXTERNAL_MODULE].channelsCount = 0; - else - g_model.moduleData[EXTERNAL_MODULE].channelsCount = MAX_PORT2_CHANNELS(); - } - break; - case 1: - if (IS_MODULE_DSM2(EXTERNAL_MODULE)) - CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, DSM2_PROTO_LP45, DSM2_PROTO_DSMX); - else - CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, RF_PROTO_X16, RF_PROTO_LAST); - if (checkIncDec_Ret) { - g_model.moduleData[EXTERNAL_MODULE].channelsStart = 0; - g_model.moduleData[EXTERNAL_MODULE].channelsCount = MAX_PORT2_CHANNELS(); - } - } - } - break; - - case ITEM_MODEL_INTERNAL_MODULE_CHANNELS: - case ITEM_MODEL_EXTERNAL_MODULE_CHANNELS: - case ITEM_MODEL_TRAINER_CHANNELS: - { - uint8_t moduleIdx = (k>=ITEM_MODEL_TRAINER_LABEL ? 2 : (k>=ITEM_MODEL_EXTERNAL_MODULE_LABEL ? 1 : 0)); - ModuleData & moduleData = g_model.moduleData[moduleIdx]; - lcd_putsLeft(y, STR_CHANNELRANGE); - if ((int8_t)PORT_CHANNELS_ROWS(moduleIdx) >= 0) { - lcd_putsAtt(MODEL_SETUP_2ND_COLUMN, y, STR_CH, m_posHorz==0 ? attr : 0); - lcd_outdezAtt(lcdLastPos, y, moduleData.channelsStart+1, LEFT | (m_posHorz==0 ? attr : 0)); - lcd_putc(lcdLastPos, y, '-'); - lcd_outdezAtt(lcdLastPos + FW+1, y, moduleData.channelsStart+NUM_CHANNELS(moduleIdx), LEFT | (m_posHorz==1 ? attr : 0)); - if (attr && (editMode>0 || p1valdiff)) { - switch (m_posHorz) { - case 0: - CHECK_INCDEC_MODELVAR_ZERO(event, moduleData.channelsStart, 32-8-moduleData.channelsCount); - break; - case 1: - CHECK_INCDEC_MODELVAR(event, moduleData.channelsCount, -4, min(MAX_CHANNELS(moduleIdx), 32-8-moduleData.channelsStart)); - if ((k == ITEM_MODEL_EXTERNAL_MODULE_CHANNELS && g_model.externalModule == MODULE_TYPE_PPM) || (k == ITEM_MODEL_TRAINER_CHANNELS)) - SET_DEFAULT_PPM_FRAME_LENGTH(moduleIdx); - break; - } - } - } - break; - } - - case ITEM_MODEL_INTERNAL_MODULE_BIND: - case ITEM_MODEL_EXTERNAL_MODULE_BIND: - case ITEM_MODEL_TRAINER_SETTINGS: - { - uint8_t moduleIdx = (k>=ITEM_MODEL_TRAINER_LABEL ? 2 : (k>=ITEM_MODEL_EXTERNAL_MODULE_LABEL ? 1 : 0)); - ModuleData & moduleData = g_model.moduleData[moduleIdx]; - if (IS_MODULE_PPM(moduleIdx)) { - lcd_putsLeft(y, STR_PPMFRAME); - lcd_puts(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_MS); - lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN, y, (int16_t)moduleData.ppmFrameLength*5 + 225, (m_posHorz<=0 ? attr : 0) | PREC1|LEFT); - lcd_putc(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, 'u'); - lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, (moduleData.ppmDelay*50)+300, (m_posHorz < 0 || m_posHorz==1) ? attr : 0); - lcd_putcAtt(MODEL_SETUP_2ND_COLUMN+10*FW, y, moduleData.ppmPulsePol ? '+' : '-', (m_posHorz < 0 || m_posHorz==2) ? attr : 0); - - if (attr && (editMode>0 || p1valdiff)) { - switch (m_posHorz) { - case 0: - CHECK_INCDEC_MODELVAR(event, moduleData.ppmFrameLength, -20, 35); - break; - case 1: - CHECK_INCDEC_MODELVAR(event, moduleData.ppmDelay, -4, 10); - break; - case 2: - CHECK_INCDEC_MODELVAR_ZERO(event, moduleData.ppmPulsePol, 1); - break; - } - } - } - else { - horzpos_t l_posHorz = m_posHorz; - uint8_t xOffsetBind = 3*FW; - if (IS_MODULE_XJT(moduleIdx) && IS_D8_RX(moduleIdx)) { - xOffsetBind = 0; - lcd_putsLeft(y, INDENT "Receiver"); - if (attr) l_posHorz += 1; - } - else { - lcd_putsLeft(y, STR_RXNUM); - } - if (IS_MODULE_XJT(moduleIdx) || IS_MODULE_DSM2(moduleIdx)) { - if (xOffsetBind) lcd_outdezNAtt(MODEL_SETUP_2ND_COLUMN, y, g_model.header.modelId, (l_posHorz==0 ? attr : 0) | LEADING0|LEFT, 2); - if (attr && l_posHorz==0) { - if (editMode>0 || p1valdiff) { - CHECK_INCDEC_MODELVAR_ZERO(event, g_model.header.modelId, IS_MODULE_DSM2(moduleIdx) ? 20 : 63); - if (checkIncDec_Ret) { - modelHeaders[g_eeGeneral.currModel].modelId = g_model.header.modelId; - } - } - if (editMode==0 && event==EVT_KEY_BREAK(KEY_ENTER)) { - checkModelIdUnique(g_eeGeneral.currModel); - } - } - lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+xOffsetBind, y, STR_MODULE_BIND, l_posHorz==1 ? attr : 0); - lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+7*FW+xOffsetBind, y, STR_MODULE_RANGE, l_posHorz==2 ? attr : 0); - if (IS_MODULE_XJT(moduleIdx)) { - uint8_t newFlag = 0; - if (attr && l_posHorz>0 && s_editMode>0) { - if (l_posHorz == 1) - newFlag = PXX_SEND_RXNUM; - else if (l_posHorz == 2) { - newFlag = PXX_SEND_RANGECHECK; - } - } - pxxFlag[moduleIdx] = newFlag; - } -#if defined(DSM2) - else { - uint8_t newFlag = 0; - if (attr && l_posHorz>0 && s_editMode>0) { - if (l_posHorz == 1) - newFlag = DSM2_BIND_FLAG; - else if (l_posHorz == 2) { - newFlag = DSM2_RANGECHECK_FLAG; - } - } - dsm2Flag = newFlag; - } -#endif - } - } - break; - } - - case ITEM_MODEL_INTERNAL_MODULE_FAILSAFE: - case ITEM_MODEL_EXTERNAL_MODULE_FAILSAFE: - { - uint8_t moduleIdx = (k>=ITEM_MODEL_EXTERNAL_MODULE_LABEL ? 1 : 0); - ModuleData & moduleData = g_model.moduleData[moduleIdx]; - lcd_putsLeft(y, TR_FAILSAFE); - if (IS_MODULE_XJT(moduleIdx)) { - lcd_putsiAtt(MODEL_SETUP_2ND_COLUMN, y, STR_VFAILSAFE, moduleData.failsafeMode, m_posHorz==0 ? attr : 0); - if (moduleData.failsafeMode == FAILSAFE_CUSTOM) lcd_putsAtt(MODEL_SETUP_2ND_COLUMN + 10*FW, y, STR_SET, m_posHorz==1 ? attr : 0); - if (attr) { - if (moduleData.failsafeMode != FAILSAFE_CUSTOM) - m_posHorz = 0; - if (m_posHorz==0) { - if (editMode>0 || p1valdiff) { - CHECK_INCDEC_MODELVAR_ZERO(event, moduleData.failsafeMode, FAILSAFE_LAST); - if (checkIncDec_Ret) SEND_FAILSAFE_NOW(moduleIdx); - } - } - else if (m_posHorz==1) { - s_editMode = 0; - if (moduleData.failsafeMode==FAILSAFE_CUSTOM && event==EVT_KEY_FIRST(KEY_ENTER)) { - g_moduleIdx = moduleIdx; - pushMenu(menuModelFailsafe); - } - } - else { - lcd_filled_rect(MODEL_SETUP_2ND_COLUMN, y, LCD_W-MODEL_SETUP_2ND_COLUMN-MENUS_SCROLLBAR_WIDTH, 8); - } - } - } - break; - } - - case ITEM_MODEL_TRAINER_LABEL: - lcd_putsLeft(y, STR_TRAINER); - break; - - case ITEM_MODEL_TRAINER_MODE: - g_model.trainerMode = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_MODE, STR_VTRAINERMODES, g_model.trainerMode, 0, 1, attr, event); - break; - -#else - - case ITEM_MODEL_PPM1_PROTOCOL: -#if defined(PCBSKY9X) - lcd_putsLeft(y, PSTR("Port1")); -#else - lcd_putsLeft(y, NO_INDENT(STR_PROTO)); -#endif - - lcd_putsiAtt(MODEL_SETUP_2ND_COLUMN, y, STR_VPROTOS, protocol, m_posHorz<=0 ? attr : 0); - -#if defined(PCBSKY9X) - lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+4*FW+3, y, STR_CH, m_posHorz==1 ? attr : 0); - lcd_outdezAtt(lcdLastPos, y, g_model.moduleData[0].channelsStart+1, LEFT | (m_posHorz==1 ? attr : 0)); - lcd_putc(lcdLastPos, y, '-'); - lcd_outdezAtt(lcdLastPos + FW+1, y, g_model.moduleData[0].channelsStart+NUM_PORT1_CHANNELS(), LEFT | (m_posHorz==2 ? attr : 0)); -#else - if (IS_PPM_PROTOCOL(protocol)) { - lcd_putsiAtt(MODEL_SETUP_2ND_COLUMN+7*FW, y, STR_NCHANNELS, g_model.ppmNCH+2, m_posHorz!=0 ? attr : 0); - } - else if (attr) { - MOVE_CURSOR_FROM_HERE(); - } -#endif - - if (attr && (editMode>0 || p1valdiff -#if !defined(PCBSKY9X) - || (!IS_PPM_PROTOCOL(protocol) && !IS_DSM2_PROTOCOL(protocol)) -#endif - )) { - switch (m_posHorz) { - case 0: - CHECK_INCDEC_MODELVAR_ZERO(event, g_model.protocol, PROTO_MAX-1); - break; - case 1: -#if defined(PCBSKY9X) - CHECK_INCDEC_MODELVAR_ZERO(event, g_model.moduleData[0].channelsStart, 32-8-g_model.moduleData[0].channelsCount); - g_model.moduleData[0].ppmFrameLength = max((int8_t)0, g_model.moduleData[0].channelsCount) * 4; - SET_DEFAULT_PPM_FRAME_LENGTH(0); -#else - CHECK_INCDEC_MODELVAR(event, g_model.ppmNCH, -2, 4); - g_model.ppmFrameLength = g_model.ppmNCH * 8; -#endif - break; -#if defined(PCBSKY9X) - case 2: - if (IS_PPM_PROTOCOL(protocol)) { - CHECK_INCDEC_MODELVAR(event, g_model.moduleData[0].channelsCount, -4, min(8, 32-8-g_model.moduleData[0].channelsStart)); - SET_DEFAULT_PPM_FRAME_LENGTH(0); - } - else - REPEAT_LAST_CURSOR_MOVE(); - break; -#endif - } - } - break; - -#if defined(PCBSKY9X) - case ITEM_MODEL_PPM2_PROTOCOL: - lcd_putsLeft(y, PSTR("Port2")); - lcd_putsiAtt(MODEL_SETUP_2ND_COLUMN, y, STR_VPROTOS, 0, 0); - lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+4*FW+3, y, STR_CH, m_posHorz<=0 ? attr : 0); - lcd_outdezAtt(lcdLastPos, y, g_model.moduleData[1].channelsStart+1, LEFT | (m_posHorz<=0 ? attr : 0)); - lcd_putc(lcdLastPos, y, '-'); - lcd_outdezAtt(lcdLastPos + FW+1, y, g_model.moduleData[1].channelsStart+8+g_model.moduleData[1].channelsCount, LEFT | (m_posHorz!=0 ? attr : 0)); - if (attr && (editMode>0 || p1valdiff)) { - switch (m_posHorz) { - case 0: - CHECK_INCDEC_MODELVAR_ZERO(event, g_model.moduleData[1].channelsStart, 32-8-g_model.moduleData[1].channelsCount); - SET_DEFAULT_PPM_FRAME_LENGTH(1); - break; - case 1: - CHECK_INCDEC_MODELVAR(event, g_model.moduleData[1].channelsCount, -4, min(8, 32-8-g_model.moduleData[1].channelsStart)); - SET_DEFAULT_PPM_FRAME_LENGTH(1); - break; - } - } - break; - - case ITEM_MODEL_PPM2_PARAMS: - lcd_putsLeft(y, STR_PPMFRAME); - lcd_puts(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_MS); - lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN, y, (int16_t)g_model.moduleData[1].ppmFrameLength*5 + 225, (m_posHorz<=0 ? attr : 0) | PREC1|LEFT); - lcd_putc(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, 'u'); - lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, (g_model.moduleData[1].ppmDelay*50)+300, (m_posHorz < 0 || m_posHorz==1) ? attr : 0); - lcd_putcAtt(MODEL_SETUP_2ND_COLUMN+10*FW, y, g_model.moduleData[1].ppmPulsePol ? '+' : '-', (m_posHorz < 0 || m_posHorz==2) ? attr : 0); - if (attr && (editMode>0 || p1valdiff)) { - switch (m_posHorz) { - case 0: - CHECK_INCDEC_MODELVAR(event, g_model.moduleData[1].ppmFrameLength, -20, 35); - break; - case 1: - CHECK_INCDEC_MODELVAR(event, g_model.moduleData[1].ppmDelay, -4, 10); - break; - case 2: - CHECK_INCDEC_MODELVAR_ZERO(event, g_model.moduleData[1].ppmPulsePol, 1); - break; - } - } - break; -#endif - - case ITEM_MODEL_PPM1_PARAMS: -#if defined(PCBSKY9X) - if (IS_PPM_PROTOCOL(protocol)) { - lcd_putsLeft(y, STR_PPMFRAME); - lcd_puts(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_MS); - lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN, y, (int16_t)g_model.moduleData[0].ppmFrameLength*5 + 225, (m_posHorz<=0 ? attr : 0) | PREC1|LEFT); - lcd_putc(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, 'u'); - lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, (g_model.moduleData[0].ppmDelay*50)+300, (m_posHorz < 0 || m_posHorz==1) ? attr : 0); - lcd_putcAtt(MODEL_SETUP_2ND_COLUMN+10*FW, y, g_model.moduleData[0].ppmPulsePol ? '+' : '-', (m_posHorz < 0 || m_posHorz==2) ? attr : 0); - if (attr && (editMode>0 || p1valdiff)) { - switch (m_posHorz) { - case 0: - CHECK_INCDEC_MODELVAR(event, g_model.moduleData[0].ppmFrameLength, -20, 35); - break; - case 1: - CHECK_INCDEC_MODELVAR(event, g_model.moduleData[0].ppmDelay, -4, 10); - break; - case 2: - CHECK_INCDEC_MODELVAR_ZERO(event, g_model.moduleData[0].ppmPulsePol, 1); - break; - } - } - } -#else - if (IS_PPM_PROTOCOL(protocol)) { - lcd_putsLeft(y, STR_PPMFRAME); - lcd_puts(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_MS); - lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN, y, (int16_t)g_model.ppmFrameLength*5 + 225, (m_posHorz<=0 ? attr : 0) | PREC1|LEFT); - lcd_putc(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, 'u'); - lcd_outdezAtt(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, (g_model.ppmDelay*50)+300, (m_posHorz < 0 || m_posHorz==1) ? attr : 0); - lcd_putcAtt(MODEL_SETUP_2ND_COLUMN+10*FW, y, g_model.pulsePol ? '+' : '-', (m_posHorz < 0 || m_posHorz==2) ? attr : 0); - if (attr && (editMode>0 || p1valdiff)) { - switch (m_posHorz) { - case 0: - CHECK_INCDEC_MODELVAR(event, g_model.ppmFrameLength, -20, 35); - break; - case 1: - CHECK_INCDEC_MODELVAR(event, g_model.ppmDelay, -4, 10); - break; - case 2: - CHECK_INCDEC_MODELVAR_ZERO(event, g_model.pulsePol, 1); - break; - } - } - } -#endif -#if defined(DSM2) || defined(PXX) - else if (IS_DSM2_PROTOCOL(protocol) || IS_PXX_PROTOCOL(protocol)) { - if (attr && m_posHorz > 1) { - REPEAT_LAST_CURSOR_MOVE(); // limit 3 column row to 2 colums (Rx_Num and RANGE fields) - } - - lcd_putsLeft(y, STR_RXNUM); - lcd_outdezNAtt(MODEL_SETUP_2ND_COLUMN, y, g_model.header.modelId, (m_posHorz<=0 ? attr : 0) | LEADING0|LEFT, 2); - if (attr && (m_posHorz==0 && (editMode>0 || p1valdiff))) { - CHECK_INCDEC_MODELVAR_ZERO(event, g_model.header.modelId, 99); -#if defined(CPUARM) - if (checkIncDec_Ret) - modelHeaders[g_eeGeneral.currModel].modelId = g_model.header.modelId; -#endif - } - -#if defined(PXX) - if (protocol == PROTO_PXX) { -#if defined(CPUARM) - if (attr && m_posHorz==0 && editMode==0 && event==EVT_KEY_BREAK(KEY_ENTER)) - checkModelIdUnique(g_eeGeneral.currModel); -#endif - - lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+4*FW, y, STR_SYNCMENU, m_posHorz!=0 ? attr : 0); - if (attr && m_posHorz>0 && editMode>0) { - // send reset code - pxxFlag[0] = PXX_SEND_RXNUM; - } - } -#endif - -#if defined(DSM2) - if (IS_DSM2_PROTOCOL(protocol)) { - lcd_putsAtt(MODEL_SETUP_2ND_COLUMN+4*FW, y, STR_MODULE_RANGE, m_posHorz!=0 ? attr : 0); - dsm2Flag = (attr && m_posHorz>0 && editMode>0) ? DSM2_RANGECHECK_FLAG : 0; // [MENU] key toggles range check mode - } -#endif - } -#endif - break; -#endif // defined(PCBTARANIS) - } - } - -#if defined(PCBTARANIS) - if (pxxFlag[INTERNAL_MODULE] == PXX_SEND_RANGECHECK || pxxFlag[EXTERNAL_MODULE] == PXX_SEND_RANGECHECK) { - displayPopup("RSSI: "); - lcd_outdezAtt(16+4*FW, 5*FH, frskyData.rssi[0].value, BOLD); - } -#endif -} - -static uint8_t s_currIdx; - -#if MENU_COLUMNS < 2 - #if LCD_W >= 212 - #define MIXES_2ND_COLUMN (18*FW) - #else - #define MIXES_2ND_COLUMN (12*FW) - #endif -#else - #define MIXES_2ND_COLUMN (9*FW) -#endif - -#if LCD_W >= 212 - #define EXPO_ONE_2ND_COLUMN (LCD_W-8*FW-90) - #define EXPO_ONE_FP_WIDTH (9*FW) -#else - #define EXPO_ONE_2ND_COLUMN (7*FW+3*FW+2) - #define EXPO_ONE_FP_WIDTH (5*FW) -#endif - -#if MENU_COLUMNS > 1 -uint8_t editDelay(const xcoord_t x, const uint8_t y, const uint8_t event, const uint8_t attr, const pm_char *str, uint8_t delay) -{ - lcd_puts(x, y, str); - lcd_outdezAtt(x+MIXES_2ND_COLUMN, y, (10/DELAY_STEP)*delay, attr|PREC1|LEFT); - if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, delay, DELAY_MAX); - return delay; -} -#define EDIT_DELAY(x, y, event, attr, str, delay) editDelay(x, y, event, attr, str, delay) -#else -uint8_t editDelay(const uint8_t y, const uint8_t event, const uint8_t attr, const pm_char *str, uint8_t delay) -{ - lcd_putsLeft(y, str); - lcd_outdezAtt(MIXES_2ND_COLUMN, y, (10/DELAY_STEP)*delay, attr|PREC1|LEFT); - if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, delay, DELAY_MAX); - return delay; -} -#define EDIT_DELAY(x, y, event, attr, str, delay) editDelay(y, event, attr, str, delay) -#endif - -#if defined(FLIGHT_MODES) - -#if defined(CPUARM) - #define FlightModesType uint16_t -#else - #define FlightModesType uint8_t -#endif - -void displayFlightModes(uint8_t x, uint8_t y, FlightModesType value) -{ - uint8_t p = MAX_PHASES; - do { - --p; - if (!(value & (1< EXPO_ONE_2ND_COLUMN-FW))) - continue; -#endif -#if defined(PCBTARANIS) - LcdFlags flags = 0; - if (attr) { - flags |= INVERS; - if (posHorz==p) flags |= BLINK; - } - if (value & (1<= 212 - -enum FlightModesItems { - ITEM_PHASES_NAME, - ITEM_PHASES_SWITCH, - ITEM_PHASES_TRIMS, - ITEM_PHASES_FADE_IN, - ITEM_PHASES_FADE_OUT, - ITEM_PHASES_COUNT, - ITEM_PHASES_LAST = ITEM_PHASES_COUNT-1 -}; - -void editPhaseTrims(uint8_t x, uint8_t y, uint8_t phase, uint8_t event, uint8_t active) -{ - static uint8_t cursorPos = 0; - - for (uint8_t t=0; t 0) { - if (p1valdiff || IS_ROTARY_RIGHT(event) || IS_ROTARY_LEFT(event) || event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_FIRST(KEY_UP) - || event==EVT_KEY_REPT(KEY_DOWN) || event==EVT_KEY_REPT(KEY_UP)) { - int16_t v = getRawTrimValue(phase, cur); - if (v < TRIM_EXTENDED_MAX) v = TRIM_EXTENDED_MAX; - v = checkIncDec(event, v, TRIM_EXTENDED_MAX, TRIM_EXTENDED_MAX+MAX_PHASES-1, EE_MODEL); - if (checkIncDec_Ret) { - if (v == TRIM_EXTENDED_MAX) v = 0; - setTrimValue(phase, cur, v); - } - } - - switch (event) { -#if defined(ROTARY_ENCODER_NAVIGATION) || defined(PCBTARANIS) - case EVT_ROTARY_BREAK: - if (s_editMode == EDIT_MODIFY_FIELD) { - s_editMode = EDIT_MODIFY_STRING; - cur = 0; - } - else if (cur0) cur--; - break; - case EVT_KEY_BREAK(KEY_RIGHT): - if (cur 0) { posHorz += 2; } - - if (sub=0) { - displayColumnHeader(STR_PHASES_HEADERS, posHorz); - } - - for (uint8_t i=0; i0) ? BLINK|INVERS : INVERS) : 0); - uint8_t active = (attr && (s_editMode>0 || p1valdiff)) ; - switch(j) - { - case ITEM_PHASES_NAME: - editName(4*FW, y, p->name, sizeof(p->name), event, attr); - break; - - case ITEM_PHASES_SWITCH: - if (k == 0) { - lcd_puts((5+LEN_FP_NAME)*FW+FW/2, y, STR_DEFAULT); - } - else { - putsSwitches((5+LEN_FP_NAME)*FW+FW/2, y, p->swtch, attr); - if (active) CHECK_INCDEC_MODELSWITCH(event, p->swtch, -MAX_SWITCH, MAX_SWITCH); - } - break; - - case ITEM_PHASES_TRIMS: - if (k != 0) { - editPhaseTrims((10+LEN_FP_NAME)*FW+FW/2, y, k, event, attr); - } - break; - - case ITEM_PHASES_FADE_IN: - lcd_outdezAtt(29*FW, y, (10/DELAY_STEP)*p->fadeIn, attr|PREC1); - if (active) p->fadeIn = checkIncDec(event, p->fadeIn, 0, DELAY_MAX, EE_MODEL|NO_INCDEC_MARKS); - break; - - case ITEM_PHASES_FADE_OUT: - lcd_outdezAtt(34*FW, y, (10/DELAY_STEP)*p->fadeOut, attr|PREC1); - if (active) p->fadeOut = checkIncDec(event, p->fadeOut, 0, DELAY_MAX, EE_MODEL|NO_INCDEC_MARKS); - break; - - } - } - } -} - -#else // LCD_W >= 212 - -enum menuModelPhaseItems { - ITEM_MODEL_PHASE_NAME, - ITEM_MODEL_PHASE_SWITCH, - ITEM_MODEL_PHASE_TRIMS, - IF_ROTARY_ENCODERS(ITEM_MODEL_PHASE_ROTARY_ENCODERS) - ITEM_MODEL_PHASE_FADE_IN, - ITEM_MODEL_PHASE_FADE_OUT, -#if defined(GVARS) && !defined(PCBSTD) - ITEM_MODEL_PHASE_GVARS_LABEL, - ITEM_MODEL_PHASE_GV1, - ITEM_MODEL_PHASE_GV2, - ITEM_MODEL_PHASE_GV3, - ITEM_MODEL_PHASE_GV4, - ITEM_MODEL_PHASE_GV5, -#endif - ITEM_MODEL_PHASE_MAX -}; - -void menuModelPhaseOne(uint8_t event) -{ - PhaseData *phase = phaseAddress(s_currIdx); - putsFlightPhase(13*FW, 0, s_currIdx+1, (getFlightPhase()==s_currIdx ? BOLD : 0)); - -#if defined(GVARS) && !defined(PCBSTD) - static const pm_uint8_t mstate_tab_phase1[] PROGMEM = {0, 0, 0, (uint8_t)-1, 1, 1, 1, 1, 1}; - static const pm_uint8_t mstate_tab_others[] PROGMEM = {0, 0, 3, IF_ROTARY_ENCODERS(NUM_ROTARY_ENCODERS-1) 0, 0, (uint8_t)-1, 2, 2, 2, 2, 2}; - - if (!check(event, 0, NULL, 0, (s_currIdx == 0) ? mstate_tab_phase1 : mstate_tab_others, DIM(mstate_tab_others)-1, ITEM_MODEL_PHASE_MAX - 1 - (s_currIdx==0 ? (ITEM_MODEL_PHASE_FADE_IN-ITEM_MODEL_PHASE_SWITCH) : 0))) return; - - TITLE(STR_MENUFLIGHTPHASE); - - #define PHASE_ONE_FIRST_LINE (1+1*FH) -#else - SUBMENU(STR_MENUFLIGHTPHASE, 3 + (s_currIdx==0 ? 0 : 2 + (bool)NUM_ROTARY_ENCODERS), {0, 0, 3, IF_ROTARY_ENCODERS(NUM_ROTARY_ENCODERS-1) 0/*, 0*/}); - #define PHASE_ONE_FIRST_LINE (1+1*FH) -#endif - - int8_t sub = m_posVert; - int8_t editMode = s_editMode; - -#if defined(GVARS) && !defined(PCBSTD) - if (s_currIdx == 0 && sub>=ITEM_MODEL_PHASE_SWITCH) sub += ITEM_MODEL_PHASE_FADE_IN-ITEM_MODEL_PHASE_SWITCH; - - for (uint8_t k=0; k=ITEM_MODEL_PHASE_SWITCH) i += ITEM_MODEL_PHASE_FADE_IN-ITEM_MODEL_PHASE_SWITCH; - uint8_t attr = (sub==i ? (editMode>0 ? BLINK|INVERS : INVERS) : 0); -#else - for (uint8_t i=0, k=0, y=PHASE_ONE_FIRST_LINE; i0 ? BLINK|INVERS : INVERS) : 0); -#endif - switch(i) { - case ITEM_MODEL_PHASE_NAME: - editSingleName(MIXES_2ND_COLUMN, y, STR_PHASENAME, phase->name, sizeof(phase->name), event, attr); - break; - case ITEM_MODEL_PHASE_SWITCH: - phase->swtch = switchMenuItem(MIXES_2ND_COLUMN, y, phase->swtch, attr, event); - break; - case ITEM_MODEL_PHASE_TRIMS: - lcd_putsLeft(y, STR_TRIMS); - for (uint8_t t=0; t0) || p1valdiff)) { - int16_t v = getRawTrimValue(s_currIdx, t); - if (v < TRIM_EXTENDED_MAX) v = TRIM_EXTENDED_MAX; - v = checkIncDec(event, v, TRIM_EXTENDED_MAX, TRIM_EXTENDED_MAX+MAX_PHASES-1, EE_MODEL); - if (checkIncDec_Ret) { - if (v == TRIM_EXTENDED_MAX) v = 0; - setTrimValue(s_currIdx, t, v); - } - } - } - break; - -#if ROTARY_ENCODERS > 0 - case ITEM_MODEL_PHASE_ROTARY_ENCODERS: - lcd_putsLeft(y, STR_ROTARY_ENCODER); - for (uint8_t t=0; t0) || p1valdiff)) { -#if ROTARY_ENCODERS > 2 - int16_t v; - if(t < (NUM_ROTARY_ENCODERS - NUM_ROTARY_ENCODERS_EXTRA)) - v = phaseAddress(s_currIdx)->rotaryEncoders[t]; - else - v = g_model.rotaryEncodersExtra[s_currIdx][t-(NUM_ROTARY_ENCODERS - NUM_ROTARY_ENCODERS_EXTRA)]; -#else - int16_t v = phaseAddress(s_currIdx)->rotaryEncoders[t]; -#endif - if (v < ROTARY_ENCODER_MAX) v = ROTARY_ENCODER_MAX; - v = checkIncDec(event, v, ROTARY_ENCODER_MAX, ROTARY_ENCODER_MAX+MAX_PHASES-1, EE_MODEL); - if (checkIncDec_Ret) { - if (v == ROTARY_ENCODER_MAX) v = 0; -#if ROTARY_ENCODERS > 2 - if (t < (NUM_ROTARY_ENCODERS - NUM_ROTARY_ENCODERS_EXTRA)) - phaseAddress(s_currIdx)->rotaryEncoders[t] = v; - else - g_model.rotaryEncodersExtra[s_currIdx][t-(NUM_ROTARY_ENCODERS - NUM_ROTARY_ENCODERS_EXTRA)] = v; -#else - phaseAddress(s_currIdx)->rotaryEncoders[t] = v; -#endif - } - } - } - break; -#endif - - case ITEM_MODEL_PHASE_FADE_IN: - phase->fadeIn = EDIT_DELAY(0, y, event, attr, STR_FADEIN, phase->fadeIn); - break; - - case ITEM_MODEL_PHASE_FADE_OUT: - phase->fadeOut = EDIT_DELAY(0, y, event, attr, STR_FADEOUT, phase->fadeOut); - break; - -#if defined(GVARS) && !defined(PCBSTD) - case ITEM_MODEL_PHASE_GVARS_LABEL: - lcd_putsLeft(y, STR_GLOBAL_VARS); - break; - - default: - { - uint8_t idx = i-ITEM_MODEL_PHASE_GV1; - uint8_t posHorz = m_posHorz; - if (attr && posHorz > 0 && s_currIdx==0) posHorz++; - - putsStrIdx(INDENT_WIDTH, y, STR_GV, idx+1); - - editName(4*FW, y, g_model.gvars[idx].name, LEN_GVAR_NAME, event, posHorz==0 ? attr : 0); - - int16_t v = phase->gvars[idx]; - if (v > GVAR_MAX) { - uint8_t p = v - GVAR_MAX - 1; - if (p >= s_currIdx) p++; - putsFlightPhase(11*FW, y, p+1, posHorz==1 ? attr : 0); - } - else { - lcd_putsAtt(11*FW, y, STR_OWN, posHorz==1 ? attr : 0); - } - if (attr && s_currIdx>0 && posHorz==1 && (editMode>0 || p1valdiff)) { - if (v < GVAR_MAX) v = GVAR_MAX; - v = checkIncDec(event, v, GVAR_MAX, GVAR_MAX+MAX_PHASES-1, EE_MODEL); - if (checkIncDec_Ret) { - if (v == GVAR_MAX) v = 0; - phase->gvars[idx] = v; - } - } - - uint8_t p = getGVarFlightPhase(s_currIdx, idx); - lcd_outdezAtt(21*FW, y, GVAR_VALUE(idx, p), posHorz==2 ? attr : 0); - if (attr && posHorz==2 && ((editMode>0) || p1valdiff)) { - GVAR_VALUE(idx, p) = checkIncDec(event, GVAR_VALUE(idx, p), -GVAR_LIMIT, GVAR_LIMIT, EE_MODEL); - } - - break; - } -#endif - } - } -} - -#if defined(ROTARY_ENCODERS) - #if ROTARY_ENCODERS > 2 - #define NAME_OFS (-4-12) - #define SWITCH_OFS (-FW/2-2-13) - #define TRIMS_OFS (-FW/2-4-15) - #define ROTARY_ENC_OFS (0) - #else - #define NAME_OFS (-4) - #define SWITCH_OFS (-FW/2-2) - #define TRIMS_OFS (-FW/2-4) - #define ROTARY_ENC_OFS (2) - #endif -#else - #define NAME_OFS 0 - #define SWITCH_OFS (FW/2) - #define TRIMS_OFS (FW/2) -#endif - -void menuModelFlightModesAll(uint8_t event) -{ - SIMPLE_MENU(STR_MENUFLIGHTPHASES, menuTabModel, e_FlightModesAll, 1+MAX_PHASES+1); - - int8_t sub = m_posVert - 1; - - switch (event) { - CASE_EVT_ROTARY_BREAK - case EVT_KEY_FIRST(KEY_ENTER): - if (sub == MAX_PHASES) { - s_editMode = 0; - trimsCheckTimer = 200; // 2 seconds - } - // no break - case EVT_KEY_FIRST(KEY_RIGHT): - if (sub >= 0 && sub < MAX_PHASES) { - s_currIdx = sub; - pushMenu(menuModelPhaseOne); - } - break; - } - - uint8_t att; - for (uint8_t i=0; i(LCD_LINES-1)*FH+1) continue; -#else - uint8_t y = 1 + (i+1)*FH; -#endif - att = (i==sub ? INVERS : 0); - PhaseData *p = phaseAddress(i); -#if ROTARY_ENCODERS > 2 - putsFlightPhase(0, y, i+1, att|CONDENSED|(getFlightPhase()==i ? BOLD : 0)); -#else - putsFlightPhase(0, y, i+1, att|(getFlightPhase()==i ? BOLD : 0)); -#endif - - lcd_putsnAtt(4*FW+NAME_OFS, y, p->name, sizeof(p->name), ZCHAR); - if (i == 0) { - lcd_puts((5+LEN_FP_NAME)*FW+SWITCH_OFS, y, STR_DEFAULT); - } - else { - putsSwitches((5+LEN_FP_NAME)*FW+SWITCH_OFS, y, p->swtch, 0); - for (uint8_t t=0; tfadeIn || p->fadeOut) - lcd_putc(LCD_W-FW-MENUS_SCROLLBAR_WIDTH, y, (p->fadeIn && p->fadeOut) ? '*' : (p->fadeIn ? 'I' : 'O')); - - } - -#if defined(CPUARM) - if (s_pgOfs != MAX_PHASES-(LCD_LINES-2)) return; -#endif - - lcd_putsLeft((LCD_LINES-1)*FH+1, STR_CHECKTRIMS); - putsFlightPhase(OFS_CHECKTRIMS, (LCD_LINES-1)*FH+1, s_perout_flight_phase+1); - if (sub==MAX_PHASES && !trimsCheckTimer) { - lcd_status_line(); - } -} - -#endif // defined(PCBTARANIS) - -#else // defined(FLIGHT_MODES) - -#define displayFlightModes(...) - -#endif - -#if defined(HELI) - -enum menuModelHeliItems { - ITEM_HELI_SWASHTYPE, - ITEM_HELI_COLLECTIVE, - ITEM_HELI_SWASHRING, - ITEM_HELI_ELEDIRECTION, - ITEM_HELI_AILDIRECTION, - ITEM_HELI_COLDIRECTION -}; - -#if LCD_W >= 212 - #define HELI_PARAM_OFS (23*FW) -#else - #define HELI_PARAM_OFS (14*FW) -#endif - -void menuModelHeli(uint8_t event) -{ - SIMPLE_MENU(STR_MENUHELISETUP, menuTabModel, e_Heli, 7); - - uint8_t sub = m_posVert - 1; - - for (uint8_t i=0; i<6; i++) { - uint8_t y = 1 + 1*FH + i*FH; - uint8_t attr = (sub == i ? ((s_editMode>0) ? BLINK|INVERS : INVERS) : 0); - switch(i) { - case ITEM_HELI_SWASHTYPE: - g_model.swashR.type = selectMenuItem(HELI_PARAM_OFS, y, STR_SWASHTYPE, STR_VSWASHTYPE, g_model.swashR.type, 0, SWASH_TYPE_NUM, attr, event); - break; - - case ITEM_HELI_COLLECTIVE: -#if defined(PCBTARANIS) - lcd_putsLeft(y, STR_COLLECTIVE); - if (attr) CHECK_INCDEC_MODELSOURCE(event, g_model.swashR.collectiveSource, 0, MIXSRC_LAST_CH); -#else - g_model.swashR.collectiveSource = selectMenuItem(HELI_PARAM_OFS, y, STR_COLLECTIVE, NULL, g_model.swashR.collectiveSource, 0, MIXSRC_LAST_CH, attr, event); -#endif - putsMixerSource(HELI_PARAM_OFS, y, g_model.swashR.collectiveSource, attr); - break; - - case ITEM_HELI_SWASHRING: - lcd_putsLeft(y, STR_SWASHRING); - lcd_outdezAtt(HELI_PARAM_OFS, y, g_model.swashR.value, LEFT|attr); - if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.swashR.value, 100); - break; - - case ITEM_HELI_ELEDIRECTION: - g_model.swashR.invertELE = selectMenuItem(HELI_PARAM_OFS, y, STR_ELEDIRECTION, STR_MMMINV, g_model.swashR.invertELE, 0, 1, attr, event); - break; - - case ITEM_HELI_AILDIRECTION: - g_model.swashR.invertAIL = selectMenuItem(HELI_PARAM_OFS, y, STR_AILDIRECTION, STR_MMMINV, g_model.swashR.invertAIL, 0, 1, attr, event); - break; - - case ITEM_HELI_COLDIRECTION: - g_model.swashR.invertCOL = selectMenuItem(HELI_PARAM_OFS, y, STR_COLDIRECTION, STR_MMMINV, g_model.swashR.invertCOL, 0, 1, attr, event); - break; - } - } -} -#endif - -typedef int16_t (*FnFuncP) (int16_t x); - -int16_t expoFn(int16_t x) -{ - ExpoData *ed = expoAddress(s_currIdx); - int16_t anas[NUM_INPUTS] = {0}; -#if defined(PCBTARANIS) - applyExpos(anas, e_perout_mode_inactive_phase, ed->srcRaw, x); -#else - anas[ed->chn] = x; - applyExpos(anas, e_perout_mode_inactive_phase); -#endif - return anas[ed->chn]; -} - -void DrawFunction(FnFuncP fn, uint8_t offset=0) -{ - lcd_vlineStip(X0-offset, 0, LCD_H, 0xee); - lcd_hlineStip(X0-WCHART-offset, Y0, WCHART*2, 0xee); - - uint8_t prev_yv = 255; - - for (int8_t xv=-WCHART; xv<=WCHART; xv++) { - uint8_t yv = (LCD_H-1) - (((uint16_t)RESX + fn(xv * (RESX/WCHART))) / 2 * (LCD_H-1) / RESX); - if (prev_yv != 255) { - if (abs((int8_t)yv-prev_yv) <= 1) { - lcd_plot(X0+xv-offset-1, prev_yv, FORCE); - } - else { - uint8_t tmp = (prev_yv < yv ? 0 : 1); - lcd_vline(X0+xv-offset-1, yv+tmp, prev_yv-yv); - } - } - prev_yv = yv; - } -} - -#if defined(CURVES) -static uint8_t s_curveChan; -int16_t curveFn(int16_t x) -{ - return applyCustomCurve(x, s_curveChan); -} - -struct point_t { - uint8_t x; - uint8_t y; -}; - -point_t getPoint(uint8_t i) -{ - point_t result = {0, 0}; -#if defined(PCBTARANIS) - CurveInfo &crv = g_model.curves[s_curveChan]; - int8_t *points = curveAddress(s_curveChan); - bool custom = (crv.type == CURVE_TYPE_CUSTOM); - uint8_t count = 5+crv.points; -#else - CurveInfo crv = curveInfo(s_curveChan); - int8_t *points = crv.crv; - bool custom = crv.custom; - uint8_t count = crv.points; -#endif - if (i < count) { -#if defined(PCBTARANIS) - result.x = X0-1-WCHART+i*WCHART*2/(count-1); -#else - result.x = X0-1-WCHART+i*WCHART/(count/2); -#endif - result.y = (LCD_H-1) - (100 + points[i]) * (LCD_H-1) / 200; - if (custom && i>0 && i g_model.points + sizeof(g_model.points)) { - AUDIO_WARNING2(); - return false; - } - - int8_t *nextCrv = curveAddress(index+1); - memmove(nextCrv+shift, nextCrv, 5*(MAX_CURVES-index-1)+curveEnd[MAX_CURVES-1]-curveEnd[index]); - if (shift < 0) memclear(&g_model.points[NUM_POINTS-1] + shift, -shift); - while (index NUM_POINTS-5*MAX_CURVES) { - AUDIO_WARNING2(); - return false; - } - - int8_t *crv = curveAddress(index); - if (shift < 0) { - for (uint8_t i=0; i0 ? INVERS|BLINK : INVERS) : 0); - lcd_putsLeft(3*FH+1, STR_TYPE); - lcd_putsiAtt(INDENT_WIDTH, 4*FH+1, "\010StandardCustom\0", crv.type, attr); - if (attr) { - uint8_t newType = checkIncDecModelZero(event, crv.type, CURVE_TYPE_LAST); - if (newType != crv.type) { - for (int i=1; i<4+crv.points; i++) - points[i] = calcRESXto100(applyCustomCurve(calc100toRESX(-100 + i*200/(4+crv.points)), s_curveChan)); - moveCurve(s_curveChan, checkIncDec_Ret > 0 ? 3+crv.points : -3-crv.points); - if (newType == CURVE_TYPE_CUSTOM) { - for (int i=0; i<3+crv.points; i++) - points[5+crv.points+i] = -100 + ((i+1)*200) / (4+crv.points); - } - crv.type = newType; - } - } - - attr = (m_posVert==2 ? (s_editMode>0 ? INVERS|BLINK : INVERS) : 0); - lcd_putsLeft(5*FH+1, "Count"); - lcd_outdezAtt(INDENT_WIDTH, 6*FH+1, 5+crv.points, LEFT|attr); - lcd_putsAtt(lcdLastPos, 6*FH+1, PSTR("pts"), attr); - if (attr) { - int8_t count = checkIncDecModel(event, crv.points, -3, 12); // 2pts - 17pts - if (checkIncDec_Ret) { - int8_t newPoints[MAX_POINTS]; - newPoints[0] = points[0]; - newPoints[4+count] = points[4+crv.points]; - for (int i=1; i<4+count; i++) - newPoints[i] = calcRESXto100(applyCustomCurve(calc100toRESX(-100 + (i*200) / (4+count)), s_curveChan)); - moveCurve(s_curveChan, checkIncDec_Ret*(crv.type==CURVE_TYPE_CUSTOM?2:1)); - for (int i=0; i<5+count; i++) { - points[i] = newPoints[i]; - if (crv.type == CURVE_TYPE_CUSTOM && i!=0 && i!=4+count) - points[5+count+i-1] = -100 + (i*200) / (4+count); - } - crv.points = count; - } - } - - lcd_putsLeft(7*FH+1, PSTR("Smooth")); - menu_lcd_onoff(7*FW, 7*FH+1, crv.smooth, m_posVert==3 ? INVERS : 0); - if (m_posVert==3) crv.smooth = checkIncDecModel(event, crv.smooth, 0, 1); - - switch(event) { - case EVT_ENTRY: - pointsOfs = 0; - SET_SCROLLBAR_X(0); - break; - case EVT_KEY_LONG(KEY_ENTER): - if (m_posVert > 1) { - killEvents(event); - MENU_ADD_ITEM(STR_CURVE_PRESET); - MENU_ADD_ITEM(STR_MIRROR); - MENU_ADD_ITEM(STR_CLEAR); - menuHandler = onCurveOneMenu; - } - break; - case EVT_KEY_LONG(KEY_MENU): - pushMenu(menuChannelsView); - killEvents(event); - return; - } - - DrawCurve(FW); - - uint8_t posY = FH+1; - attr = (s_editMode > 0 ? INVERS|BLINK : INVERS); - for (uint8_t i=0; i<5+crv.points; i++) { - point_t point = getPoint(i); - uint8_t selectionMode = 0; - if (crv.type==CURVE_TYPE_CUSTOM) { - if (m_posVert==4+2*i || (i==5+crv.points-1 && m_posVert==4+5+crv.points+5+crv.points-2-1)) - selectionMode = 2; - else if (i>0 && m_posVert==3+2*i) - selectionMode = 1; - } - else if (m_posVert == 4+i) { - selectionMode = 2; - } - - if (i>=pointsOfs && i0 && i<5+crv.points-1) x = points[5+crv.points+i-1]; - lcd_outdezAtt(6+8*FW, posY, i+1, LEFT); - lcd_outdezAtt(3+12*FW, posY, x, LEFT|(selectionMode==1?attr:0)); - lcd_outdezAtt(3+16*FW, posY, points[i], LEFT|(selectionMode==2?attr:0)); - posY += FH; - } - - if (selectionMode > 0) { - // do selection square - lcd_filled_rect(point.x-FW-1, point.y-2, 5, 5, SOLID, FORCE); - lcd_filled_rect(point.x-FW, point.y-1, 3, 3, SOLID); - if (s_editMode > 0) { - if (selectionMode == 1) - CHECK_INCDEC_MODELVAR(event, points[5+crv.points+i-1], i==1 ? -100 : points[5+crv.points+i-2], i==5+crv.points-2 ? 100 : points[5+crv.points+i]); // edit X - else if (selectionMode == 2) - CHECK_INCDEC_MODELVAR(event, points[i], -100, 100); - } - if (i < pointsOfs) - pointsOfs = i; - else if (i > pointsOfs+6) - pointsOfs = i-6; - } - } -} -#else -void menuModelCurveOne(uint8_t event) -{ - TITLE(STR_MENUCURVE); - lcd_outdezAtt(PSIZE(TR_MENUCURVE)*FW+1, 0, s_curveChan+1, INVERS|LEFT); - DISPLAY_PROGRESS_BAR(20*FW+1); - - CurveInfo crv = curveInfo(s_curveChan); - - switch(event) { - case EVT_ENTRY: - s_editMode = 1; - break; - CASE_EVT_ROTARY_BREAK - case EVT_KEY_BREAK(KEY_ENTER): - if (s_editMode <= 0) - m_posHorz = 0; - if (s_editMode == 1 && crv.custom) - s_editMode = 2; - else - s_editMode = 1; - break; - case EVT_KEY_LONG(KEY_ENTER): - if (s_editMode <= 0) { - if (int8_t(++m_posHorz) > 4) - m_posHorz = -4; - for (uint8_t i=0; i 0) { - if (--s_editMode == 0) - m_posHorz = 0; - } - else { - popMenu(); - } - break; - - /* CASE_EVT_ROTARY_LEFT */ - case EVT_KEY_REPT(KEY_LEFT): - case EVT_KEY_FIRST(KEY_LEFT): - if (s_editMode==1 && m_posHorz>0) m_posHorz--; - if (s_editMode <= 0) { - if (crv.custom) { - moveCurve(s_curveChan, -crv.points+2); - } - else if (crv.points > MIN_POINTS) { - moveCurve(s_curveChan, -1, (crv.points+1)/2); - } - else { - AUDIO_WARNING2(); - } - return; - } - break; - - /* CASE_EVT_ROTARY_RIGHT */ - case EVT_KEY_REPT(KEY_RIGHT): - case EVT_KEY_FIRST(KEY_RIGHT): - if (s_editMode==1 && m_posHorz<(crv.points-1)) m_posHorz++; - if (s_editMode <= 0) { - if (!crv.custom) { - moveCurve(s_curveChan, crv.points-2, crv.points); - } - else if (crv.points < MAX_POINTS) { - if (moveCurve(s_curveChan, 1)) { - for (int8_t i=crv.points+crv.points-2; i>=0; i--) { - if (i%2) - crv.crv[i] = (crv.crv[i/2] + crv.crv[1+i/2]) / 2; - else - crv.crv[i] = crv.crv[i/2]; - } - } - } - else { - AUDIO_WARNING2(); - } - } - break; - } - - lcd_putsLeft(7*FH, STR_TYPE); - uint8_t attr = (s_editMode <= 0 ? INVERS : 0); - lcd_outdezAtt(5*FW-2, 7*FH, crv.points, LEFT|attr); - lcd_putsAtt(lcdLastPos, 7*FH, crv.custom ? PSTR("pt'") : PSTR("pt"), attr); - - DrawCurve(); - - if (s_editMode>0) { - uint8_t i = m_posHorz; - point_t point = getPoint(i); - - if (s_editMode==1 || !BLINK_ON_PHASE) { - // do selection square - lcd_filled_rect(point.x-1, point.y-2, 5, 5, SOLID, FORCE); - lcd_filled_rect(point.x, point.y-1, 3, 3, SOLID); - } - - int8_t x = -100 + 200*i/(crv.points-1); - if (crv.custom && i>0 && i=0; i--) { - ch = (expo ? EXPO_VALID(expoAddress(i)) : mixAddress(i)->srcRaw); - if (ch != 0) { - count++; - } - } - return count; -} - -bool reachExpoMixCountLimit(uint8_t expo) -{ - // check mixers count limit - if (getExpoMixCount(expo) >= (expo ? MAX_EXPOS : MAX_MIXERS)) { - POPUP_WARNING(expo ? STR_NOFREEEXPO : STR_NOFREEMIXER); - return true; - } - return false; -} - -void deleteExpoMix(uint8_t expo, uint8_t idx) -{ - pauseMixerCalculations(); - if (expo) { - ExpoData *expo = expoAddress(idx); - memmove(expo, expo+1, (MAX_EXPOS-(idx+1))*sizeof(ExpoData)); - memclear(&g_model.expoData[MAX_EXPOS-1], sizeof(ExpoData)); - } - else { - MixData *mix = mixAddress(idx); - memmove(mix, mix+1, (MAX_MIXERS-(idx+1))*sizeof(MixData)); - memclear(&g_model.mixData[MAX_MIXERS-1], sizeof(MixData)); - } - resumeMixerCalculations(); - eeDirty(EE_MODEL); -} - -// TODO avoid this global s_currCh on ARM boards ... -int8_t s_currCh; -void insertExpoMix(uint8_t expo, uint8_t idx) -{ - pauseMixerCalculations(); - if (expo) { - ExpoData *expo = expoAddress(idx); - memmove(expo+1, expo, (MAX_EXPOS-(idx+1))*sizeof(ExpoData)); - memclear(expo, sizeof(ExpoData)); -#if defined(PCBTARANIS) - expo->srcRaw = (s_currCh > 4 ? MIXSRC_Rud - 1 + s_currCh : MIXSRC_Rud - 1 + channel_order(s_currCh)); - expo->curve.type = CURVE_REF_EXPO; -#else - expo->mode = 3; // pos&neg -#endif - expo->chn = s_currCh - 1; - expo->weight = 100; - } - else { - MixData *mix = mixAddress(idx); - memmove(mix+1, mix, (MAX_MIXERS-(idx+1))*sizeof(MixData)); - memclear(mix, sizeof(MixData)); - mix->destCh = s_currCh-1; -#if defined(PCBTARANIS) - mix->srcRaw = s_currCh; - if (!isSourceAvailable(mix->srcRaw)) - mix->srcRaw = (s_currCh > 4 ? MIXSRC_Rud - 1 + s_currCh : MIXSRC_Rud - 1 + channel_order(s_currCh)); -#else - mix->srcRaw = (s_currCh > 4 ? MIXSRC_Rud - 1 + s_currCh : MIXSRC_Rud - 1 + channel_order(s_currCh)); -#endif - mix->weight = 100; - } - resumeMixerCalculations(); - eeDirty(EE_MODEL); -} - -void copyExpoMix(uint8_t expo, uint8_t idx) -{ - pauseMixerCalculations(); - if (expo) { - ExpoData *expo = expoAddress(idx); - memmove(expo+1, expo, (MAX_EXPOS-(idx+1))*sizeof(ExpoData)); - } - else { - MixData *mix = mixAddress(idx); - memmove(mix+1, mix, (MAX_MIXERS-(idx+1))*sizeof(MixData)); - } - resumeMixerCalculations(); - eeDirty(EE_MODEL); -} - -void memswap(void *a, void *b, uint8_t size) -{ - uint8_t *x = (uint8_t*)a; - uint8_t *y = (uint8_t*)b; - uint8_t temp ; - - while (size--) { - temp = *x; - *x++ = *y; - *y++ = temp; - } -} - -bool swapExpoMix(uint8_t expo, uint8_t &idx, uint8_t up) -{ - void *x, *y; - uint8_t size; - int8_t tgt_idx = (up ? idx-1 : idx+1); - - if (expo) { - x = (ExpoData *)expoAddress(idx); - - if (tgt_idx < 0) { - if (((ExpoData *)x)->chn == 0) - return false; - ((ExpoData *)x)->chn--; - return true; - } - - if (tgt_idx == MAX_EXPOS) { - if (((ExpoData *)x)->chn == NUM_STICKS-1) - return false; - ((ExpoData *)x)->chn++; - return true; - } - - y = (ExpoData *)expoAddress(tgt_idx); - if(((ExpoData *)x)->chn != ((ExpoData *)y)->chn || !EXPO_VALID((ExpoData *)y)) { - if (up) { - if (((ExpoData *)x)->chn>0) ((ExpoData *)x)->chn--; - else return false; - } - else { - if (((ExpoData *)x)->chnchn++; - else return false; - } - return true; - } - - size = sizeof(ExpoData); - } - else { - x = (MixData *)mixAddress(idx); - - if (tgt_idx < 0) { - if (((MixData *)x)->destCh == 0) - return false; - ((MixData *)x)->destCh--; - return true; - } - - if (tgt_idx == MAX_MIXERS) { - if (((MixData *)x)->destCh == NUM_CHNOUT-1) - return false; - ((MixData *)x)->destCh++; - return true; - } - - y = (MixData *)mixAddress(tgt_idx); - uint8_t destCh = ((MixData *)x)->destCh; - if(!((MixData *)y)->srcRaw || destCh != ((MixData *)y)->destCh) { - if (up) { - if (destCh>0) ((MixData *)x)->destCh--; - else return false; - } - else { - if (destChdestCh++; - else return false; - } - return true; - } - - size = sizeof(MixData); - } - - pauseMixerCalculations(); - memswap(x, y, size); - resumeMixerCalculations(); - - idx = tgt_idx; - return true; -} - -enum ExposFields { - CASE_PCBTARANIS(EXPO_FIELD_INPUT_NAME) - IF_CPUARM(EXPO_FIELD_NAME) - CASE_PCBTARANIS(EXPO_FIELD_SOURCE) - CASE_PCBTARANIS(EXPO_FIELD_SCALE) - EXPO_FIELD_WEIGHT, - CASE_PCBTARANIS(EXPO_FIELD_OFFSET) - CASE_9X(EXPO_FIELD_EXPO) - IF_CURVES(EXPO_FIELD_CURVE) - IF_FLIGHT_MODES(EXPO_FIELD_FLIGHT_PHASE) - EXPO_FIELD_SWITCH, - CASE_9X(EXPO_FIELD_SIDE) - CASE_PCBTARANIS(EXPO_FIELD_TRIM) - EXPO_FIELD_MAX -}; - -#if defined(PCBTARANIS) - #define CURVE_ROWS 1 -#else - #define CURVE_ROWS 0 -#endif - -void menuModelExpoOne(uint8_t event) -{ -#if defined(PCBTARANIS) - if (event == EVT_KEY_LONG(KEY_MENU)) { - pushMenu(menuChannelsView); - killEvents(event); - return; - } -#endif - - ExpoData *ed = expoAddress(s_currIdx); -#if defined(PCBTARANIS) - putsMixerSource(7*FW+FW/2, 0, MIXSRC_FIRST_INPUT+ed->chn, 0); -#else - putsMixerSource(7*FW+FW/2, 0, MIXSRC_Rud+ed->chn, 0); -#endif - - SUBMENU(STR_MENUINPUTS, EXPO_FIELD_MAX, {CASE_PCBTARANIS(0) IF_CPUARM(0) CASE_PCBTARANIS(0) CASE_PCBTARANIS((ed->srcRaw >= MIXSRC_FIRST_TELEM ? (uint8_t)0 : (uint8_t)HIDDEN_ROW)) 0, CASE_PCBTARANIS(0) CASE_9X(0) IF_CURVES(CURVE_ROWS) IF_FLIGHT_MODES((MAX_PHASES-1) | NAVIGATION_LINE_BY_LINE) 0 /*, ...*/}); - - SET_SCROLLBAR_X(EXPO_ONE_2ND_COLUMN+10*FW); - - int8_t sub = m_posVert; - - uint8_t y = FH+1; - -#if defined(PCBTARANIS) - for (uint8_t k=0; k0 ? BLINK|INVERS : INVERS) : 0); - switch(i) - { -#if defined(PCBTARANIS) - case EXPO_FIELD_INPUT_NAME: - editSingleName(EXPO_ONE_2ND_COLUMN, y, "Input Name", g_model.inputNames[ed->chn], sizeof(g_model.inputNames[ed->chn]), event, attr); - break; -#endif - -#if defined(CPUARM) - case EXPO_FIELD_NAME: - editSingleName(EXPO_ONE_2ND_COLUMN-IF_9X(sizeof(ed->name)*FW), y, STR_EXPONAME, ed->name, sizeof(ed->name), event, attr); - break; -#endif - -#if defined(PCBTARANIS) - case EXPO_FIELD_SOURCE: - lcd_putsLeft(y, NO_INDENT(STR_SOURCE)); - putsMixerSource(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw, STREXPANDED|attr); - if (attr) ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isInputSourceAvailable); - break; - - case EXPO_FIELD_SCALE: - lcd_putsLeft(y, STR_SCALE); - putsTelemetryChannel(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw - MIXSRC_FIRST_TELEM, convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale), LEFT|attr); - if (attr) ed->scale = checkIncDec(event, ed->scale, 0, maxTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1), EE_MODEL, NULL); - break; -#endif - - case EXPO_FIELD_WEIGHT: - lcd_putsLeft(y, STR_WEIGHT); - ed->weight = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->weight, MIN_EXPO_WEIGHT, 100, IF_PCBTARANIS(LEFT)|attr, 0, event); - break; - -#if defined(PCBTARANIS) - case EXPO_FIELD_OFFSET: - lcd_putsLeft(y, NO_INDENT(STR_OFFSET)); - ed->offset = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->offset, -100, 100, LEFT|attr, 0, event); - break; -#endif - -#if !defined(PCBTARANIS) - case EXPO_FIELD_EXPO: - lcd_putsLeft(y, STR_EXPO); - if (ed->curveMode==MODE_EXPO || ed->curveParam==0) { - ed->curveMode = MODE_EXPO; - ed->curveParam = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->curveParam, -100, 100, attr, 0, event); - } - else { - lcd_putsAtt(EXPO_ONE_2ND_COLUMN-3*FW, y, STR_NA, attr); - } - break; -#endif - -#if defined(CURVES) - case EXPO_FIELD_CURVE: - lcd_putsLeft(y, STR_CURVE); -#if defined(PCBTARANIS) - editCurveRef(EXPO_ONE_2ND_COLUMN, y, ed->curve, event, attr); -#else - if (ed->curveMode!=MODE_EXPO || ed->curveParam==0) { - putsCurve(EXPO_ONE_2ND_COLUMN-3*FW, y, ed->curveParam, attr); - if (attr) { - CHECK_INCDEC_MODELVAR_ZERO(event, ed->curveParam, CURVE_BASE+MAX_CURVES-1); - if (ed->curveParam) ed->curveMode = MODE_CURVE; - if (ed->curveParam>=CURVE_BASE && event==EVT_KEY_LONG(KEY_ENTER)) { - s_curveChan = ed->curveParam - CURVE_BASE; - pushMenu(menuModelCurveOne); - } - } - } - else { - lcd_putsAtt(EXPO_ONE_2ND_COLUMN-3*FW, y, STR_NA, attr); - } -#endif - break; -#endif - -#if defined(FLIGHT_MODES) - case EXPO_FIELD_FLIGHT_PHASE: - ed->phases = editFlightModes(EXPO_ONE_2ND_COLUMN-IF_9X(EXPO_ONE_FP_WIDTH), y, event, ed->phases, attr); - break; -#endif - - case EXPO_FIELD_SWITCH: - ed->swtch = switchMenuItem(EXPO_ONE_2ND_COLUMN-IF_9X(3*FW), y, ed->swtch, attr, event); - break; - -#if !defined(PCBTARANIS) - case EXPO_FIELD_SIDE: - ed->mode = 4 - selectMenuItem(EXPO_ONE_2ND_COLUMN-3*FW, y, STR_SIDE, STR_VSIDE, 4-ed->mode, 1, 3, attr, event); - break; -#endif - -#if defined(PCBTARANIS) - case EXPO_FIELD_TRIM: - uint8_t not_stick = (ed->srcRaw > MIXSRC_Ail); - int8_t carryTrim = -ed->carryTrim; - lcd_putsLeft(y, STR_TRIM); - lcd_putsiAtt(EXPO_ONE_2ND_COLUMN, y, STR_VMIXTRIMS, (not_stick && carryTrim == 0) ? 0 : carryTrim+1, m_posHorz==0 ? attr : 0); - if (attr) ed->carryTrim = -checkIncDecModel(event, carryTrim, not_stick ? TRIM_ON : -TRIM_OFF, -TRIM_AIL); - break; -#endif - } - y += FH; - } - - DrawFunction(expoFn); - -#if defined(PCBTARANIS) - int x512 = getValue(ed->srcRaw); - if (ed->srcRaw >= MIXSRC_FIRST_TELEM) { - putsTelemetryChannel(LCD_W-8, 6*FH, ed->srcRaw - MIXSRC_FIRST_TELEM, x512, 0); - if (ed->scale > 0) x512 = (x512 * 1024) / convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale); - x512 = limit(-1024, x512, 1024); - } - else { - lcd_outdezAtt(LCD_W-8, 6*FH, calcRESXto1000(x512), PREC1); - } - int y512 = expoFn(x512); - lcd_outdezAtt(LCD_W-8-6*FW, 1*FH, calcRESXto1000(y512), PREC1); -#else - int16_t x512 = calibratedStick[ed->chn]; - lcd_outdezAtt(LCD_W-8, 6*FH, calcRESXto100(x512), 0); - int16_t y512 = expoFn(x512); - lcd_outdezAtt(LCD_W-8-6*FW, 1*FH, calcRESXto100(y512), 0); -#endif - - x512 = X0+x512/(RESXu/WCHART); -#if defined(CPUARM) - y512 = (LCD_H-1) - ((y512+RESX)/2) * (LCD_H-1) / RESX; -#else - y512 = (LCD_H-1) - (uint16_t)((y512+RESX)/2) * (LCD_H-1) / RESX; -#endif - - lcd_vline(x512, y512-3, 3*2+1); - lcd_hline(x512-3, y512, 3*2+1); -} - -enum MixFields { - IF_CPUARM(MIX_FIELD_NAME) - MIX_FIELD_SOURCE, - MIX_FIELD_WEIGHT, - MIX_FIELD_OFFSET, - CASE_9X(MIX_FIELD_TRIM) - IF_CURVES(MIX_FIELD_CURVE) - IF_FLIGHT_MODES(MIX_FIELD_FLIGHT_PHASE) - MIX_FIELD_SWITCH, - MIX_FIELD_WARNING, - MIX_FIELD_MLTPX, - MIX_FIELD_DELAY_UP, - MIX_FIELD_DELAY_DOWN, - MIX_FIELD_SLOW_UP, - MIX_FIELD_SLOW_DOWN, - MIX_FIELD_COUNT -}; - -void gvarWeightItem(xcoord_t x, uint8_t y, MixData *md, uint8_t attr, uint8_t event) -{ - u_int8int16_t weight; - MD_WEIGHT_TO_UNION(md, weight); - weight.word = GVAR_MENU_ITEM(x, y, weight.word, -500, 500, attr, 0, event); - MD_UNION_TO_WEIGHT(weight, md); -} - -void menuModelMixOne(uint8_t event) -{ -#if defined(PCBTARANIS) - if (event == EVT_KEY_LONG(KEY_MENU)) { - pushMenu(menuChannelsView); - killEvents(event); - return; - } -#endif - - TITLE(s_currCh ? STR_INSERTMIX : STR_EDITMIX); - MixData *md2 = mixAddress(s_currIdx) ; - putsChn(lcdLastPos+1*FW, 0, md2->destCh+1,0); - -#if defined(ROTARY_ENCODERS) -#if defined(CURVES) - if ((m_posVert == MIX_FIELD_TRIM && md2->srcRaw > NUM_STICKS) || (m_posVert == MIX_FIELD_CURVE && md2->curveMode == MODE_CURVE)) -#else - if (m_posVert == MIX_FIELD_TRIM && md2->srcRaw > NUM_STICKS) -#endif - SUBMENU_NOTITLE(MIX_FIELD_COUNT, {IF_CPUARM(0) 0, 0, 0, CASE_9X(0) IF_CURVES(0) IF_FLIGHT_MODES((MAX_PHASES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/}) - else - SUBMENU_NOTITLE(MIX_FIELD_COUNT, {IF_CPUARM(0) 0, 0, 0, CASE_9X(1) IF_CURVES(1) IF_FLIGHT_MODES((MAX_PHASES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/}); -#else - SUBMENU_NOTITLE(MIX_FIELD_COUNT, {IF_CPUARM(0) 0, 0, 0, CASE_9X(1) IF_CURVES(1) IF_FLIGHT_MODES((MAX_PHASES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/}); -#endif - -#if MENU_COLUMNS > 1 - lcd_vline(MENU_COLUMN2_X-4, FH+1, LCD_H-FH-1); -#endif - - int8_t sub = m_posVert; - int8_t editMode = s_editMode; - - for (uint8_t k=0; k 1 - uint8_t y; - uint8_t COLUMN_X; - if (k >= LCD_LINES-1) { - y = 1 + (k-LCD_LINES+2)*FH; - COLUMN_X = MENU_COLUMN2_X; - } - else { - y = 1 + (k+1)*FH; - COLUMN_X = 0; - } - int8_t i = k; -#else - uint8_t y = 1 + (k+1)*FH; - int8_t i = k + s_pgOfs; -#endif - - uint8_t attr = (sub==i ? (editMode>0 ? BLINK|INVERS : INVERS) : 0); - switch(i) { -#if defined(CPUARM) - case MIX_FIELD_NAME: - editSingleName(COLUMN_X+MIXES_2ND_COLUMN, y, STR_MIXNAME, md2->name, sizeof(md2->name), event, attr); - break; -#endif - case MIX_FIELD_SOURCE: - lcd_putsColumnLeft(COLUMN_X, y, NO_INDENT(STR_SOURCE)); - putsMixerSource(COLUMN_X+MIXES_2ND_COLUMN, y, md2->srcRaw, STREXPANDED|attr); - if (attr) CHECK_INCDEC_MODELSOURCE(event, md2->srcRaw, 1, MIXSRC_LAST); - break; - case MIX_FIELD_WEIGHT: - lcd_putsColumnLeft(COLUMN_X, y, STR_WEIGHT); - gvarWeightItem(COLUMN_X+MIXES_2ND_COLUMN, y, md2, attr|LEFT, event); - break; - case MIX_FIELD_OFFSET: - { - lcd_putsColumnLeft(COLUMN_X, y, NO_INDENT(STR_OFFSET)); - u_int8int16_t offset; - MD_OFFSET_TO_UNION(md2, offset); - offset.word = GVAR_MENU_ITEM(COLUMN_X+MIXES_2ND_COLUMN, y, offset.word, GV_RANGELARGE_NEG, GV_RANGELARGE, attr|LEFT, 0, event); - MD_UNION_TO_OFFSET(offset, md2); - break; - } - -#if !defined(PCBTARANIS) - case MIX_FIELD_TRIM: - { - uint8_t not_stick = (md2->srcRaw > NUM_STICKS); - int8_t carryTrim = -md2->carryTrim; - lcd_putsColumnLeft(COLUMN_X, y, STR_TRIM); -#if LCD_W >= 212 && defined(TRANSLATIONS_FR) - lcd_putsiAtt((not_stick ? COLUMN_X+MIXES_2ND_COLUMN : COLUMN_X+11*FW-3), y, STR_VMIXTRIMS, (not_stick && carryTrim == 0) ? 0 : carryTrim+1, m_posHorz==0 ? attr : 0); -#else - lcd_putsiAtt((not_stick ? COLUMN_X+MIXES_2ND_COLUMN : COLUMN_X+6*FW-3), y, STR_VMIXTRIMS, (not_stick && carryTrim == 0) ? 0 : carryTrim+1, m_posHorz==0 ? attr : 0); -#endif - if (attr && m_posHorz==0 && (not_stick || editMode>0)) md2->carryTrim = -checkIncDecModel(event, carryTrim, not_stick ? TRIM_ON : -TRIM_OFF, -TRIM_AIL); - if (!not_stick) { - lcd_puts(COLUMN_X+MIXES_2ND_COLUMN, y, STR_DREX); - menu_lcd_onoff(COLUMN_X+MIXES_2ND_COLUMN+5*FW, y, !md2->noExpo, m_posHorz==1 ? attr : 0); - if (attr && m_posHorz==1 && editMode>0) md2->noExpo = !checkIncDecModel(event, !md2->noExpo, 0, 1); - } - else if (attr) { - REPEAT_LAST_CURSOR_MOVE(); - } - break; - } -#endif - -#if defined(CURVES) - case MIX_FIELD_CURVE: - { - lcd_putsColumnLeft(COLUMN_X, y, STR_CURVE); -#if defined(PCBTARANIS) - editCurveRef(COLUMN_X+MIXES_2ND_COLUMN, y, md2->curve, event, attr); -#else - int8_t curveParam = md2->curveParam; - if (md2->curveMode == MODE_CURVE) { - putsCurve(COLUMN_X+MIXES_2ND_COLUMN, y, curveParam, attr); - if (attr) { - if (event==EVT_KEY_LONG(KEY_ENTER) && (curveParam<0 || curveParam>=CURVE_BASE)){ - s_curveChan = (curveParam<0 ? -curveParam-1 : curveParam-CURVE_BASE); - pushMenu(menuModelCurveOne); - } - else { - CHECK_INCDEC_MODELVAR(event, md2->curveParam, -MAX_CURVES, CURVE_BASE+MAX_CURVES-1); - if (md2->curveParam == 0) - md2->curveMode = MODE_DIFFERENTIAL; -#if defined(ROTARY_ENCODER_NAVIGATION) || defined(PCBTARANIS) - MOVE_CURSOR_FROM_HERE(); -#else - m_posHorz = 0; -#endif - } - } - } - else { - lcd_putsAtt(COLUMN_X+MIXES_2ND_COLUMN, y, PSTR("Diff"), m_posHorz==0 ? attr : 0); - md2->curveParam = GVAR_MENU_ITEM(COLUMN_X+MIXES_2ND_COLUMN+5*FW, y, curveParam, -100, 100, LEFT|(m_posHorz==1 ? attr : 0), 0, editMode>0 ? event : 0); - if (attr && editMode>0 && m_posHorz==0) { - int8_t tmp = 0; - CHECK_INCDEC_MODELVAR(event, tmp, -1, 1); - if (tmp != 0) { - md2->curveMode = MODE_CURVE; - md2->curveParam = tmp; - } - } - } -#endif - break; - } -#endif -#if defined(FLIGHT_MODES) - case MIX_FIELD_FLIGHT_PHASE: - md2->phases = editFlightModes(COLUMN_X+MIXES_2ND_COLUMN, y, event, md2->phases, attr); - break; -#endif - case MIX_FIELD_SWITCH: - md2->swtch = switchMenuItem(COLUMN_X+MIXES_2ND_COLUMN, y, md2->swtch, attr, event); - break; - case MIX_FIELD_WARNING: - lcd_putsColumnLeft(COLUMN_X+MIXES_2ND_COLUMN, y, STR_MIXWARNING); - if (md2->mixWarn) - lcd_outdezAtt(COLUMN_X+MIXES_2ND_COLUMN, y, md2->mixWarn, attr|LEFT); - else - lcd_putsAtt(COLUMN_X+MIXES_2ND_COLUMN, y, STR_OFF, attr); - if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, md2->mixWarn, 3); - break; - case MIX_FIELD_MLTPX: - md2->mltpx = selectMenuItem(COLUMN_X+MIXES_2ND_COLUMN, y, STR_MULTPX, STR_VMLTPX, md2->mltpx, 0, 2, attr, event); - break; - case MIX_FIELD_DELAY_UP: - md2->delayUp = EDIT_DELAY(COLUMN_X, y, event, attr, STR_DELAYUP, md2->delayUp); - break; - case MIX_FIELD_DELAY_DOWN: - md2->delayDown = EDIT_DELAY(COLUMN_X, y, event, attr, STR_DELAYDOWN, md2->delayDown); - break; - case MIX_FIELD_SLOW_UP: - md2->speedUp = EDIT_DELAY(COLUMN_X, y, event, attr, STR_SLOWUP, md2->speedUp); - break; - case MIX_FIELD_SLOW_DOWN: - md2->speedDown = EDIT_DELAY(COLUMN_X, y, event, attr, STR_SLOWDOWN, md2->speedDown); - break; - } - } -} - -static uint8_t s_maxLines = 8; -static uint8_t s_copySrcIdx; -static uint8_t s_copySrcCh; - -#define _STR_MAX(x) PSTR("/" #x) -#define STR_MAX(x) _STR_MAX(x) - -#define MIX_LINE_SRC_POS 4*FW-1 - -#if LCD_W >= 212 - #define EXPO_LINE_WEIGHT_POS 8*FW+1 - #define EXPO_LINE_SRC_POS 9*FW-2 - #define EXPO_LINE_CURVE_POS 12*FW+4 - #define EXPO_LINE_SWITCH_POS 17*FW-1 - #define EXPO_LINE_SELECT_POS 5*FW+2 - #define EXPO_LINE_FM_POS LCD_W-LEN_EXPOMIX_NAME*FW-MENUS_SCROLLBAR_WIDTH-FW-1 - #define EXPO_LINE_NAME_POS LCD_W-LEN_EXPOMIX_NAME*FW-MENUS_SCROLLBAR_WIDTH - #define MIX_LINE_WEIGHT_POS 11*FW+5 - #define MIX_LINE_CURVE_POS 12*FW+4 - #define MIX_LINE_SWITCH_POS 16*FW+1 - #define MIX_LINE_DELAY_POS 19*FW+2 -#elif defined(CPUARM) - #define EXPO_LINE_WEIGHT_POS 7*FW-1 - #define EXPO_LINE_EXPO_POS 10*FW+5 - #define EXPO_LINE_SWITCH_POS 11*FW+2 - #define EXPO_LINE_SIDE_POS 14*FW+2 - #define EXPO_LINE_SELECT_POS 24 - #define EXPO_LINE_FM_POS - #define EXPO_LINE_NAME_POS LCD_W-sizeof(ed->name)*FW-MENUS_SCROLLBAR_WIDTH - #define MIX_LINE_WEIGHT_POS 11*FW+3 - #define MIX_LINE_CURVE_POS 12*FW+2 - #define MIX_LINE_SWITCH_POS 16*FW - #define MIX_LINE_DELAY_POS 19*FW+7 -#else - #define EXPO_LINE_WEIGHT_POS 7*FW-1 - #define EXPO_LINE_EXPO_POS 11*FW - #define EXPO_LINE_SWITCH_POS 11*FW+4 - #if MAX_PHASES == 6 - #define EXPO_LINE_SIDE_POS 15*FW - #else - #define EXPO_LINE_SIDE_POS 15*FW+2 - #endif - #define EXPO_LINE_FM_POS LCD_W-FW-MENUS_SCROLLBAR_WIDTH - #define EXPO_LINE_SELECT_POS 24 - #define MIX_LINE_WEIGHT_POS 11*FW+3 - #define MIX_LINE_CURVE_POS 12*FW+2 - #define MIX_LINE_SWITCH_POS 16*FW - #define MIX_LINE_DELAY_POS 19*FW+7 -#endif - -#if defined(NAVIGATION_MENUS) -void onExpoMixMenu(const char *result) -{ - bool expo = (g_menuStack[g_menuStackPtr] == menuModelExposAll); - uint8_t chn = (expo ? expoAddress(s_currIdx)->chn+1 : mixAddress(s_currIdx)->destCh+1); - - if (result == STR_EDIT) { - pushMenu(expo ? menuModelExpoOne : menuModelMixOne); - } - else if (result == STR_INSERT_BEFORE || result == STR_INSERT_AFTER) { - if (!reachExpoMixCountLimit(expo)) { - s_currCh = chn; - if (result == STR_INSERT_AFTER) { s_currIdx++; m_posVert++; } - insertExpoMix(expo, s_currIdx); - pushMenu(expo ? menuModelExpoOne : menuModelMixOne); - } - } - else if (result == STR_COPY || result == STR_MOVE) { - s_copyMode = (result == STR_COPY ? COPY_MODE : MOVE_MODE); - s_copySrcIdx = s_currIdx; - s_copySrcCh = chn; - s_copySrcRow = m_posVert; - } - else if (result == STR_DELETE) { - deleteExpoMix(expo, s_currIdx); - } -} -#endif - -#if LCD_W >= 212 -void displayHeaderChannelName(uint8_t ch) -{ - uint8_t len = zlen(g_model.limitData[ch-1].name, sizeof(g_model.limitData[ch-1].name)); - if (len) { - lcd_putc(17*FW, 0, ' '); - lcd_putsnAtt(18*FW, 0, g_model.limitData[ch-1].name, len, ZCHAR); - lcd_putc(18*FW+len*FW, 0, ' '); - } -} -#endif - -void menuModelExpoMix(uint8_t expo, uint8_t event) -{ - uint8_t sub = m_posVert; - - if (s_editMode > 0) - s_editMode = 0; - - uint8_t chn = (expo ? expoAddress(s_currIdx)->chn+1 : mixAddress(s_currIdx)->destCh+1); - - switch (event) - { - case EVT_ENTRY: - case EVT_ENTRY_UP: - s_copyMode = 0; - s_copyTgtOfs = 0; - break; - case EVT_KEY_LONG(KEY_EXIT): - if (s_copyMode && s_copyTgtOfs == 0) { - deleteExpoMix(expo, s_currIdx); - killEvents(event); - event = 0; - } - // no break -#if defined(ROTARY_ENCODER_NAVIGATION) - case EVT_ROTARY_LONG: - if (s_copyMode) { - killEvents(event); - } -#endif - case EVT_KEY_BREAK(KEY_EXIT): - if (s_copyMode) { - if (s_copyTgtOfs) { - // cancel the current copy / move operation - if (s_copyMode == COPY_MODE) { - deleteExpoMix(expo, s_currIdx); - } - else { - do { - swapExpoMix(expo, s_currIdx, s_copyTgtOfs > 0); - s_copyTgtOfs += (s_copyTgtOfs < 0 ? +1 : -1); - } while (s_copyTgtOfs != 0); - eeDirty(EE_MODEL); - } - m_posVert = s_copySrcRow; - s_copyTgtOfs = 0; - } - s_copyMode = 0; - event = 0; - } - break; - case EVT_KEY_BREAK(KEY_ENTER): - if (sub != 0 && (!s_currCh || (s_copyMode && !s_copyTgtOfs)) && !READ_ONLY()) { - s_copyMode = (s_copyMode == COPY_MODE ? MOVE_MODE : COPY_MODE); - s_copySrcIdx = s_currIdx; - s_copySrcCh = chn; - s_copySrcRow = sub; - break; - } - // no break - - CASE_EVT_ROTARY_BREAK - case EVT_KEY_LONG(KEY_ENTER): - killEvents(event); - if (s_copyTgtOfs) { - s_copyMode = 0; - s_copyTgtOfs = 0; - } - else if (sub != 0) { - if (READ_ONLY()) { - if (!s_currCh) { - pushMenu(expo ? menuModelExpoOne : menuModelMixOne); - return; - } - } - else { - if (s_copyMode) s_currCh = 0; -#if defined(NAVIGATION_MENUS) - if (s_currCh) { - if (reachExpoMixCountLimit(expo)) break; - insertExpoMix(expo, s_currIdx); - pushMenu(expo ? menuModelExpoOne : menuModelMixOne); - s_copyMode = 0; - return; - } - else { - event = 0; - s_copyMode = 0; - MENU_ADD_ITEM(STR_EDIT); - MENU_ADD_ITEM(STR_INSERT_BEFORE); - MENU_ADD_ITEM(STR_INSERT_AFTER); - MENU_ADD_ITEM(STR_COPY); - MENU_ADD_ITEM(STR_MOVE); - MENU_ADD_ITEM(STR_DELETE); - menuHandler = onExpoMixMenu; - } -#else - if (s_currCh) { - if (reachExpoMixCountLimit(expo)) break; - insertExpoMix(expo, s_currIdx); - } - pushMenu(expo ? menuModelExpoOne : menuModelMixOne); - s_copyMode = 0; - return; -#endif - } - } - break; - case EVT_KEY_LONG(KEY_LEFT): - case EVT_KEY_LONG(KEY_RIGHT): - if (s_copyMode && !s_copyTgtOfs) { - if (reachExpoMixCountLimit(expo)) break; - s_currCh = chn; - if (event == EVT_KEY_LONG(KEY_RIGHT)) { s_currIdx++; m_posVert++; } - insertExpoMix(expo, s_currIdx); - pushMenu(expo ? menuModelExpoOne : menuModelMixOne); - s_copyMode = 0; - killEvents(event); - return; - } - break; -#if defined(ROTARY_ENCODER_NAVIGATION) - case EVT_ROTARY_LEFT: - case EVT_ROTARY_RIGHT: -#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) { - uint8_t key = (event & 0x1f); - uint8_t next_ofs = ((IS_ROTARY_UP(event) || key==KEY_MOVE_UP) ? s_copyTgtOfs - 1 : s_copyTgtOfs + 1); - - if (s_copyTgtOfs==0 && s_copyMode==COPY_MODE) { - // insert a mix on the same channel (just above / just below) - if (reachExpoMixCountLimit(expo)) break; - copyExpoMix(expo, s_currIdx); - if (IS_ROTARY_DOWN(event) || key==KEY_MOVE_DOWN) s_currIdx++; - else if (sub-s_pgOfs >= 6) s_pgOfs++; - } - else if (next_ofs==0 && s_copyMode==COPY_MODE) { - // delete the mix - deleteExpoMix(expo, s_currIdx); - if (IS_ROTARY_UP(event) || key==KEY_MOVE_UP) s_currIdx--; - } - else { - // only swap the mix with its neighbor - if (!swapExpoMix(expo, s_currIdx, IS_ROTARY_UP(event) || key==KEY_MOVE_UP)) break; - eeDirty(EE_MODEL); - } - - s_copyTgtOfs = next_ofs; - } - break; - } - - lcd_outdezAtt(FW*max(sizeof(TR_MENUINPUTS), sizeof(TR_MIXER))+FW+FW/2, 0, getExpoMixCount(expo)); - lcd_puts(FW*max(sizeof(TR_MENUINPUTS), sizeof(TR_MIXER))+FW+FW/2, 0, expo ? STR_MAX(MAX_EXPOS) : STR_MAX(MAX_MIXERS)); - SIMPLE_MENU(expo ? STR_MENUINPUTS : STR_MIXER, menuTabModel, expo ? e_InputsAll : e_MixAll, s_maxLines); - - sub = m_posVert; - s_currCh = 0; - uint8_t cur = 1; - uint8_t i = 0; - - for (uint8_t ch=1; ch<=(expo ? NUM_INPUTS : NUM_CHNOUT); ch++) { - void *pointer = NULL; MixData * &md = (MixData * &)pointer; ExpoData * &ed = (ExpoData * &)pointer; - uint8_t y = 1+(cur-s_pgOfs)*FH; - if (expo ? (ichn+1 == ch && EXPO_VALID(ed)) : (isrcRaw && md->destCh+1 == ch)) { - if (s_pgOfs < cur && cur-s_pgOfs < LCD_LINES) { - if (expo) { -#if defined(PCBTARANIS) - putsMixerSource(0, y, ch, 0); -#else - putsMixerSource(0, y, MIXSRC_Rud+ch-1, 0); -#endif - } - else { - putsChn(0, y, ch, 0); // show CHx - } - } - uint8_t mixCnt = 0; - do { - if (s_copyMode) { - if (s_copyMode == MOVE_MODE && s_pgOfs < cur && cur-s_pgOfs < 8 && s_copySrcCh == ch && s_copyTgtOfs != 0 && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { - lcd_rect(expo ? 18 : 22, y-1, expo ? LCD_W-18 : LCD_W-22, 9, DOTTED); - cur++; y+=FH; - } - if (s_currIdx == i) { - sub = m_posVert = cur; - s_currCh = ch; - } - } - else if (sub == cur) { - s_currIdx = i; - } - if (s_pgOfs < cur && cur-s_pgOfs < 8) { - uint8_t attr = ((s_copyMode || sub != cur) ? 0 : INVERS); - if (expo) { - ed->weight = GVAR_MENU_ITEM(EXPO_LINE_WEIGHT_POS, y, ed->weight, MIN_EXPO_WEIGHT, 100, attr | (isExpoActive(i) ? BOLD : 0), 0, event); - -#if defined(PCBTARANIS) - putsMixerSource(EXPO_LINE_SRC_POS, y, ed->srcRaw, 0); -#endif - -#if defined(PCBTARANIS) - putsCurveRef(EXPO_LINE_CURVE_POS, y, ed->curve, 0); -#else - if (ed->curveMode == MODE_CURVE) - putsCurve(EXPO_LINE_EXPO_POS-3*FW, y, ed->curveParam); - else - displayGVar(EXPO_LINE_EXPO_POS, y, ed->curveParam, -100, 100); -#endif - - putsSwitches(EXPO_LINE_SWITCH_POS, y, ed->swtch, 0); - -#if !defined(PCBTARANIS) - if (ed->mode!=3) lcd_putc(EXPO_LINE_SIDE_POS, y, ed->mode == 2 ? 126 : 127); -#endif - -#if defined(CPUARM) && LCD_W >= 212 - displayFlightModes(EXPO_LINE_FM_POS, y, ed->phases); - if (ed->name[0]) lcd_putsnAtt(EXPO_LINE_NAME_POS, y, ed->name, sizeof(ed->name), ZCHAR | (isExpoActive(i) ? BOLD : 0)); -#elif defined(CPUARM) - if (ed->name[0]) lcd_putsnAtt(EXPO_LINE_NAME_POS, y, ed->name, sizeof(ed->name), ZCHAR | (isExpoActive(i) ? BOLD : 0)); -#else - displayFlightModes(EXPO_LINE_FM_POS, y, ed->phases); -#endif - } - else { -#if LCD_W >= 212 - if (attr) { - displayHeaderChannelName(ch); - } -#endif - - if (mixCnt > 0) lcd_putsiAtt(FW, y, STR_VMLTPX2, md->mltpx, 0); - - putsMixerSource(MIX_LINE_SRC_POS, y, md->srcRaw, isMixActive(i) ? BOLD : 0); - - gvarWeightItem(MIX_LINE_WEIGHT_POS, y, md, attr, event); - -#if LCD_W >= 212 - displayFlightModes(EXPO_LINE_FM_POS, y, md->phases); -#endif - -#if defined(CPUARM) - if (md->name[0]) { - lcd_putsnAtt(EXPO_LINE_NAME_POS, y, md->name, sizeof(md->name), ZCHAR | (isMixActive(i) ? BOLD : 0)); - } -#if LCD_W < 212 - else -#endif -#endif - { -#if defined(PCBTARANIS) -#else - if (md->curveParam) { - if (md->curveMode == MODE_CURVE) - putsCurve(MIX_LINE_CURVE_POS, y, md->curveParam); - else - displayGVar(MIX_LINE_CURVE_POS+3*FW, y, md->curveParam, -100, 100); - } -#endif - if (md->swtch) putsSwitches(MIX_LINE_SWITCH_POS, y, md->swtch); - - char cs = ' '; - if (md->speedDown || md->speedUp) - cs = 'S'; - if ((md->delayUp || md->delayDown)) - cs = (cs =='S' ? '*' : 'D'); - lcd_putc(MIX_LINE_DELAY_POS, y, cs); - } - } - if (s_copyMode) { - if ((s_copyMode==COPY_MODE || s_copyTgtOfs == 0) && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { - /* draw a border around the raw on selection mode (copy/move) */ - lcd_rect(expo ? EXPO_LINE_SELECT_POS : 22, y-1, expo ? (LCD_W-EXPO_LINE_SELECT_POS) : (LCD_W-22), 9, s_copyMode == COPY_MODE ? SOLID : DOTTED); - } - if (cur == sub) { - /* invert the raw when it's the current one */ - lcd_filled_rect(expo ? EXPO_LINE_SELECT_POS+1 : 23, y, expo ? (LCD_W-EXPO_LINE_SELECT_POS-2) : (LCD_W-24), 7); - } - } - } - cur++; y+=FH; mixCnt++; i++; if (expo) ed++; else md++; - } while (expo ? (ichn+1 == ch && EXPO_VALID(ed)) : (isrcRaw && md->destCh+1 == ch)); - if (s_copyMode == MOVE_MODE && s_pgOfs < cur && cur-s_pgOfs < LCD_LINES && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) { - lcd_rect(expo ? EXPO_LINE_SELECT_POS : 22, y-1, expo ? LCD_W-EXPO_LINE_SELECT_POS : LCD_W-22, 9, DOTTED); - cur++; y+=FH; - } - } - else { - uint8_t attr = 0; - if (sub == cur) { - s_currIdx = i; - s_currCh = ch; - if (!s_copyMode) { - attr = INVERS; - } - } - if (s_pgOfs < cur && cur-s_pgOfs < LCD_LINES) { - if (expo) { -#if defined(PCBTARANIS) - putsMixerSource(0, y, ch, attr); -#else - putsMixerSource(0, y, MIXSRC_Rud+ch-1, attr); -#endif - } - else { - putsChn(0, y, ch, attr); // show CHx -#if LCD_W >= 212 - if (attr) { - displayHeaderChannelName(ch); - } -#endif - } - if (s_copyMode == MOVE_MODE && s_copySrcCh == ch) { - lcd_rect(expo ? EXPO_LINE_SELECT_POS : 22, y-1, expo ? (LCD_W-EXPO_LINE_SELECT_POS) : (LCD_W-22), 9, DOTTED); - } - } - cur++; y+=FH; - } - } - s_maxLines = cur; - if (sub >= s_maxLines-1) m_posVert = s_maxLines-1; -} - -void menuModelExposAll(uint8_t event) -{ - return menuModelExpoMix(1, event); -} - -void menuModelMixAll(uint8_t event) -{ - return menuModelExpoMix(0, event); -} - -bool thrOutput(uint8_t ch) -{ - for (uint8_t i=0; idestCh==ch && mix->srcRaw==MIXSRC_Thr) - return true; - } - return false; -} - -enum LimitsItems { -#if defined(PCBTARANIS) - ITEM_LIMITS_CH_NAME, -#endif - ITEM_LIMITS_OFFSET, - ITEM_LIMITS_MIN, - ITEM_LIMITS_MAX, - ITEM_LIMITS_DIRECTION, -#if defined(PCBTARANIS) && defined(CURVES) - ITEM_LIMITS_CURVE, -#endif -#if defined(PPM_CENTER_ADJUSTABLE) - ITEM_LIMITS_PPM_CENTER, -#endif -#if defined(PPM_LIMITS_SYMETRICAL) - ITEM_LIMITS_SYMETRICAL, -#endif - ITEM_LIMITS_COUNT, - ITEM_LIMITS_MAXROW = ITEM_LIMITS_COUNT-1 -}; - -#if defined(PCBTARANIS) - #define LIMITS_NAME_POS 4*FW - #define LIMITS_OFFSET_POS 14*FW+4 - #define LIMITS_MIN_POS 20*FW-3 - #if defined(PPM_CENTER_ADJUSTABLE) - #define LIMITS_DIRECTION_POS 20*FW-3 - #define LIMITS_MAX_POS 24*FW+2 - #define LIMITS_REVERT_POS 25*FW-1 - #define LIMITS_CURVE_POS 27*FW-1 - #define LIMITS_PPM_CENTER_POS 34*FW - #else - #define LIMITS_DIRECTION_POS 21*FW - #define LIMITS_MAX_POS 26*FW - #define LIMITS_REVERT_POS 27*FW - #define LIMITS_CURVE_POS 32*FW - #endif -#else - #if defined(PPM_UNIT_US) - #define LIMITS_MIN_POS 12*FW+1 - #else - #define LIMITS_MIN_POS 12*FW - #endif - #define LIMITS_OFFSET_POS 8*FW - #if defined(PPM_LIMITS_SYMETRICAL) - #if defined(PPM_CENTER_ADJUSTABLE) - #define LIMITS_MAX_POS 15*FW - #define LIMITS_REVERT_POS 16*FW-3 - #define LIMITS_PPM_CENTER_POS 20*FW+1 - #else - #define LIMITS_DIRECTION_POS 12*FW+4 - #define LIMITS_MAX_POS 16*FW+4 - #define LIMITS_REVERT_POS 17*FW - #endif - #else - #if defined(PPM_CENTER_ADJUSTABLE) - #define LIMITS_MAX_POS 16*FW - #define LIMITS_REVERT_POS 17*FW-2 - #define LIMITS_PPM_CENTER_POS 21*FW+2 - #else - #define LIMITS_MAX_POS 17*FW - #define LIMITS_REVERT_POS 18*FW - #define LIMITS_DIRECTION_POS 12*FW+5 - #endif - #endif -#endif - -#if defined(CPUARM) - #define LIMITS_MIN_MAX_OFFSET 1000 - #define CONVERT_US_MIN_MAX(x) (((x)*128)/250) - #define MIN_MAX_LIMIT (10*limit) - #define MIN_MAX_ATTR attr|PREC1 -#else - #define LIMITS_MIN_MAX_OFFSET 100 - #define CONVERT_US_MIN_MAX(x) ((int16_t(x)*128)/25) - #define MIN_MAX_LIMIT (limit) - #define MIN_MAX_ATTR attr -#endif - -#if defined(PPM_UNIT_US) - #define MIN_MAX_DISPLAY(x) CONVERT_US_MIN_MAX(x) - #undef MIN_MAX_ATTR - #define MIN_MAX_ATTR attr -#else - #define MIN_MAX_DISPLAY(x) (x) -#endif - -#if defined(PCBTARANIS) -void onLimitsMenu(const char *result) -{ - uint8_t ch = m_posVert - 1; - - if (result == STR_RESET) { - LimitData *ld = limitAddress(ch); - ld->min = 0; - ld->max = 0; - ld->offset = 0; - ld->ppmCenter = 0; - ld->revert = false; - ld->curve = 0; - } - else if (result == STR_COPY_TRIMS_TO_OFFSET) { - copyTrimsToOffset(ch); - } -} -#endif - -void menuModelLimits(uint8_t event) -{ - uint8_t sub = m_posVert - 1; - - if (sub < NUM_CHNOUT) { -#if defined(PPM_CENTER_ADJUSTABLE) || defined(PPM_UNIT_US) - lcd_outdezAtt(13*FW, 0, PPM_CH_CENTER(sub)+channelOutputs[sub]/2, 0); - lcd_puts(13*FW, 0, STR_US); -#else - lcd_outdezAtt(13*FW, 0, calcRESXto1000(channelOutputs[sub]), PREC1); -#endif - } - -#if defined(CPUARM) - MENU(STR_MENULIMITS, menuTabModel, e_Limits, 1+NUM_CHNOUT+1, {0, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, 0}); -#else - MENU(STR_MENULIMITS, menuTabModel, e_Limits, 1+NUM_CHNOUT+1, {0, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, 0}); -#endif - -#if LCD_W >= 212 - if (sub=0) { - displayColumnHeader(STR_LIMITS_HEADERS, m_posHorz); - } -#endif - - if (s_warning_result) { - s_warning_result = 0; - LimitData *ld = limitAddress(sub); - ld->revert = !ld->revert; - eeDirty(EE_MODEL); - } - - for (uint8_t i=0; i= 212 || !defined(PPM_CENTER_ADJUSTABLE) - int16_t v = (ld->revert) ? -ld->offset : ld->offset; - char swVal = '-'; // '-', '<', '>' - if((channelOutputs[k] - v) > 50) swVal = (ld->revert ? 127 : 126); // Switch to raw inputs? - remove trim! - if((channelOutputs[k] - v) < -50) swVal = (ld->revert ? 126 : 127); - putsChn(0, y, k+1, 0); - lcd_putc(LIMITS_DIRECTION_POS, y, swVal); -#endif - -#if defined(PPM_CENTER_ADJUSTABLE) - int8_t limit = ((g_model.extendedLimits && !limitAddress(k)->ppmCenter) ? 125 : 100); -#else - int8_t limit = (g_model.extendedLimits ? 125 : 100); -#endif - -#if defined(PCBTARANIS) - putsChn(0, y, k+1, (sub==k && m_posHorz < 0) ? INVERS : 0); - if (sub==k && m_posHorz < 0 && event==EVT_KEY_LONG(KEY_ENTER)) { - killEvents(event); - MENU_ADD_ITEM(STR_RESET); - MENU_ADD_ITEM(STR_COPY_TRIMS_TO_OFFSET); - menuHandler = onLimitsMenu; - } -#else - putsChn(0, y, k+1, 0); -#endif - - for (uint8_t j=0; j0) ? BLINK|INVERS : INVERS) : 0); - uint8_t active = (attr && (s_editMode>0 || p1valdiff)) ; - if (active) STICK_SCROLL_DISABLE(); - switch(j) - { -#if defined(PCBTARANIS) - case ITEM_LIMITS_CH_NAME: - editName(LIMITS_NAME_POS, y, ld->name, sizeof(ld->name), event, attr); - break; -#endif - - case ITEM_LIMITS_OFFSET: -#if defined(PCBTARANIS) - ld->offset = GVAR_MENU_ITEM(LIMITS_OFFSET_POS, y, MIN_MAX_DISPLAY(ld->offset), -1000, 1000, attr|PREC1, 0, event); -#else - #if defined(PPM_UNIT_US) - lcd_outdezAtt(LIMITS_OFFSET_POS, y, ((int32_t)ld->offset*128) / 25, attr|PREC1); - #else - lcd_outdezAtt(LIMITS_OFFSET_POS, y, ld->offset, attr|PREC1); - #endif - if (active) { - ld->offset = checkIncDec(event, ld->offset, -1000, 1000, EE_MODEL|NO_INCDEC_MARKS); - } - else if (attr && event==EVT_KEY_LONG(KEY_MENU)) { - copyTrimsToOffset(k); - s_editMode = 0; - } -#endif - break; - - case ITEM_LIMITS_MIN: -#if defined(CPUARM) - ld->min = LIMITS_MIN_MAX_OFFSET + GVAR_MENU_ITEM(LIMITS_MIN_POS, y, MIN_MAX_DISPLAY(ld->min-LIMITS_MIN_MAX_OFFSET), -MIN_MAX_LIMIT, 0, MIN_MAX_ATTR, DBLKEYS_1000, event); -#else - lcd_outdezAtt(LIMITS_MIN_POS, y, MIN_MAX_DISPLAY(ld->min-LIMITS_MIN_MAX_OFFSET), MIN_MAX_ATTR); - if (active) ld->min = LIMITS_MIN_MAX_OFFSET + checkIncDecModel(event, ld->min-LIMITS_MIN_MAX_OFFSET, -MIN_MAX_LIMIT, 0); -#endif - break; - - case ITEM_LIMITS_MAX: -#if defined(CPUARM) - ld->max = -LIMITS_MIN_MAX_OFFSET + GVAR_MENU_ITEM(LIMITS_MAX_POS, y, MIN_MAX_DISPLAY(ld->max+LIMITS_MIN_MAX_OFFSET), 0, MIN_MAX_LIMIT, MIN_MAX_ATTR, DBLKEYS_1000, event); -#else - lcd_outdezAtt(LIMITS_MAX_POS, y, MIN_MAX_DISPLAY(ld->max+LIMITS_MIN_MAX_OFFSET), MIN_MAX_ATTR); - if (active) ld->max = -LIMITS_MIN_MAX_OFFSET + checkIncDecModelZero(event, ld->max+LIMITS_MIN_MAX_OFFSET, +MIN_MAX_LIMIT); -#endif - break; - - case ITEM_LIMITS_DIRECTION: - { - uint8_t revert = ld->revert; -#if defined(PPM_CENTER_ADJUSTABLE) - lcd_putcAtt(LIMITS_REVERT_POS, y, revert ? 127 : 126, attr); -#else - lcd_putsiAtt(LIMITS_REVERT_POS, y, STR_MMMINV, revert, attr); -#endif - if (active) { - uint8_t revert_new = checkIncDecModel(event, revert, 0, 1); - if (checkIncDec_Ret && thrOutput(k)) { - POPUP_CONFIRMATION(STR_INVERT_THR); - } - else { - ld->revert = revert_new; - } - } - break; - } - -#if defined(PCBTARANIS) && defined(CURVES) - case ITEM_LIMITS_CURVE: - putsCurve(LIMITS_CURVE_POS, y, ld->curve, attr); - if (attr && event==EVT_KEY_LONG(KEY_ENTER) && ld->curve>0) { - s_curveChan = (ld->curve<0 ? -ld->curve-1 : ld->curve-1); - pushMenu(menuModelCurveOne); - } - if (active) { - CHECK_INCDEC_MODELVAR(event, ld->curve, -MAX_CURVES, +MAX_CURVES); - } - break; -#endif - -#if defined(PPM_CENTER_ADJUSTABLE) - case ITEM_LIMITS_PPM_CENTER: - lcd_outdezAtt(LIMITS_PPM_CENTER_POS, y, PPM_CENTER+ld->ppmCenter, attr); -#pragma message("could be less restrictive!") - if (active && ld->max <= 0 && ld->min >= 0) { - CHECK_INCDEC_MODELVAR(event, ld->ppmCenter, -125, +125); - } - break; -#endif - -#if defined(PPM_LIMITS_SYMETRICAL) - case ITEM_LIMITS_SYMETRICAL: - lcd_putcAtt(LCD_W-FW-MENUS_SCROLLBAR_WIDTH, y, ld->symetrical ? '=' : '^', attr); - if (active) { - CHECK_INCDEC_MODELVAR_ZERO(event, ld->symetrical, 1); - } - break; -#endif - } - } - } -} - -#if defined(CURVES) - -#if defined(GVARS) - #define CURVE_SELECTED() (sub >= 0 && sub < MAX_CURVES) - #define GVAR_SELECTED() (sub >= MAX_CURVES) -#else - #define CURVE_SELECTED() (sub >= 0) -#endif - -void menuModelCurvesAll(uint8_t event) -{ -#if defined(GVARS) && defined(PCBSTD) - SIMPLE_MENU(STR_MENUCURVES, menuTabModel, e_CurvesAll, 1+MAX_CURVES+MAX_GVARS); -#else - SIMPLE_MENU(STR_MENUCURVES, menuTabModel, e_CurvesAll, 1+MAX_CURVES); -#endif - - int8_t sub = m_posVert - 1; - - switch (event) { -#if defined(ROTARY_ENCODER_NAVIGATION) - case EVT_ROTARY_BREAK: -#endif -#if defined(PCBTARANIS) - case EVT_KEY_BREAK(KEY_ENTER): -#else - case EVT_KEY_FIRST(KEY_RIGHT): - case EVT_KEY_FIRST(KEY_ENTER): -#endif - if (CURVE_SELECTED() && !READ_ONLY()) { - s_curveChan = sub; - pushMenu(menuModelCurveOne); - } - break; - } - - for (uint8_t i=0; i= MAX_CURVES) { - putsStrIdx(0, y, STR_GV, k-MAX_CURVES+1); - if (GVAR_SELECTED()) { - if (attr && s_editMode>0) attr |= BLINK; - lcd_outdezAtt(10*FW, y, GVAR_VALUE(k-MAX_CURVES, -1), attr); - if (attr) g_model.gvars[k-MAX_CURVES] = checkIncDec(event, g_model.gvars[k-MAX_CURVES], -1000, 1000, EE_MODEL); - } - } - else -#endif - { - putsStrIdx(0, y, STR_CV, k+1, attr); -#if defined(PCBTARANIS) - editName(4*FW, y, g_model.curveNames[k], sizeof(g_model.curveNames[k]), 0, 0); - CurveInfo & crv = g_model.curves[k]; - lcd_outdezAtt(11*FW, y, 5+crv.points, LEFT); - lcd_putsAtt(lcdLastPos, y, PSTR("pts"), 0); -#endif - } - } - - if (CURVE_SELECTED()) { - s_curveChan = sub; - DrawCurve(23); - } -} -#endif - -#if LCD_W >= 212 && defined(GVARS) && defined(FLIGHT_MODES) - -void onGVARSMenu(const char *result) -{ - int8_t sub = m_posVert - 1; - - if (result == STR_ENABLE_POPUP) { - g_model.gvars[sub].popup = true; - eeDirty(EE_MODEL); - } - else if (result == STR_DISABLE_POPUP) { - g_model.gvars[sub].popup = false; - eeDirty(EE_MODEL); - } - else if (result == STR_CLEAR) { - for (int i=0; i 6 - for (uint8_t l=0; l0) ? BLINK|INVERS : INVERS) : 0); - xcoord_t x = 12*FW + FWNUM + (j-1)*(2+3*FWNUM) - 3; - -#if MAX_GVARS == 6 - if (i==0 && j!=9) putsStrIdx(x+2, FH+1, STR_FP, j, SMLSIZE); -#elif MAX_GVARS <= 5 - if (i==0 && j!=9) putsStrIdx(x+2, 2*FH, STR_FP, j, SMLSIZE); -#endif - - switch(j) - { - case 0: - editName(4*FW-3, y, g_model.gvars[i].name, LEN_GVAR_NAME, event, attr); - break; - - default: - { - PhaseData *phase = &g_model.phaseData[j-1]; - int16_t & v = phase->gvars[i]; - int16_t vmin, vmax; - if (v > GVAR_MAX) { - uint8_t p = v - GVAR_MAX - 1; - if (p >= j-1) p++; - putsFlightPhase(x-15, y, p+1, attr|SMLSIZE); - vmin = GVAR_MAX+1; vmax = GVAR_MAX+MAX_PHASES-1; - } - else { - if (abs(v) >= 100) - lcd_outdezAtt(x, y+1, v, attr | TINSIZE); - else - lcd_outdezAtt(x, y, v, attr); - vmin = -GVAR_MAX; vmax = GVAR_MAX; - } - if (attr) { - if (event == EVT_KEY_LONG(KEY_ENTER)) { - s_editMode = 2; // TODO constant for that ... - v = (v > GVAR_MAX ? 0 : GVAR_MAX+1); - eeDirty(EE_MODEL); - } - else if (s_editMode>0 || p1valdiff) { - v = checkIncDec(event, v, vmin, vmax, EE_MODEL); - } - } - break; - } - } - } - } - -#if defined(CPUARM) - #define INCDEC_DECLARE_VARS() uint8_t incdecFlag = EE_MODEL; IsValueAvailable isValueAvailable = NULL - #define INCDEC_SET_FLAG(f) incdecFlag = (EE_MODEL|(f)) - #define INCDEC_ENABLE_CHECK(fn) isValueAvailable = fn - #define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, incdecFlag, isValueAvailable) -#elif defined(CPUM64) - #define INCDEC_DECLARE_VARS() - #define INCDEC_SET_FLAG(f) - #define INCDEC_ENABLE_CHECK(fn) - #define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, EE_MODEL) -#else - #define INCDEC_DECLARE_VARS() uint8_t incdecFlag = EE_MODEL - #define INCDEC_SET_FLAG(f) incdecFlag = (EE_MODEL|(f)) - #define INCDEC_ENABLE_CHECK(fn) - #define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, incdecFlag) -#endif - - if (m_posVert > 0 && m_posHorz < 0 && event==EVT_KEY_LONG(KEY_ENTER)) { - killEvents(event); - if (g_model.gvars[sub].popup) - MENU_ADD_ITEM(STR_DISABLE_POPUP); - else - MENU_ADD_ITEM(STR_ENABLE_POPUP); - MENU_ADD_ITEM(STR_CLEAR); - menuHandler = onGVARSMenu; - } -} -#endif - -#if defined(CPUARM) - #define INCDEC_DECLARE_VARS() uint8_t incdecFlag = EE_MODEL; IsValueAvailable isValueAvailable = NULL - #define INCDEC_SET_FLAG(f) incdecFlag = (EE_MODEL|(f)) - #define INCDEC_ENABLE_CHECK(fn) isValueAvailable = fn - #define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, incdecFlag, isValueAvailable) -#elif defined(CPUM64) - #define INCDEC_DECLARE_VARS() - #define INCDEC_SET_FLAG(f) - #define INCDEC_ENABLE_CHECK(fn) - #define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, EE_MODEL) -#else - #define INCDEC_DECLARE_VARS() uint8_t incdecFlag = EE_MODEL - #define INCDEC_SET_FLAG(f) incdecFlag = (EE_MODEL|(f)) - #define INCDEC_ENABLE_CHECK(fn) - #define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, incdecFlag) -#endif - -enum CustomSwitchFields { - CSW_FIELD_FUNCTION, - CSW_FIELD_V1, - CSW_FIELD_V2, - CSW_FIELD_ANDSW, -#if defined(CPUARM) - CSW_FIELD_DURATION, - CSW_FIELD_DELAY, -#endif - CSW_FIELD_COUNT, - CSW_FIELD_LAST = CSW_FIELD_COUNT-1 -}; - -#if LCD_W >= 212 - #define CSW_1ST_COLUMN (4*FW-3) - #define CSW_2ND_COLUMN (8*FW+1) - #define CSW_3RD_COLUMN (14*FW) - #define CSW_4TH_COLUMN (21*FW+1) - #define CSW_5TH_COLUMN (26*FW+1) - #define CSW_6TH_COLUMN (31*FW+1) -#else - #define CSW_1ST_COLUMN (4*FW-3) - #define CSW_2ND_COLUMN (8*FW-3) - #define CSW_3RD_COLUMN (13*FW-6) - #define CSW_4TH_COLUMN (18*FW+2) -#endif - -#if defined(CPUARM) && LCD_W < 212 - -#define CSWONE_2ND_COLUMN (11*FW) - -void menuModelCustomSwitchOne(uint8_t event) -{ - TITLE(STR_MENUCUSTOMSWITCH); - - CustomSwData * cs = cswAddress(s_currIdx); - uint8_t sw = SWSRC_SW1+s_currIdx; - putsSwitches(14*FW, 0, sw, (getSwitch(sw) ? BOLD : 0)); - SIMPLE_SUBMENU_NOTITLE(CSW_FIELD_COUNT); - - int8_t sub = m_posVert; - - for (uint8_t k=0; k0 ? BLINK|INVERS : INVERS) : 0); - uint8_t cstate = cswFamily(cs->func); - switch(i) { - case CSW_FIELD_FUNCTION: - lcd_putsLeft(y, STR_FUNC); - lcd_putsiAtt(CSWONE_2ND_COLUMN, y, STR_VCSWFUNC, cs->func, attr); - if (attr) { - CHECK_INCDEC_MODELVAR_ZERO(event, cs->func, CS_MAXF); - if (cstate != cswFamily(cs->func)) { - cs->v1 = 0; - cs->v2 = 0; - } - } - break; - case CSW_FIELD_V1: - { - lcd_putsLeft(y, STR_V1); - int8_t v1_min=0, v1_max=MIXSRC_LAST_TELEM; - if (cstate == CS_VBOOL) { - putsSwitches(CSWONE_2ND_COLUMN, y, cs->v1, attr); - v1_min = SWSRC_OFF+1; v1_max = SWSRC_ON-1; - } - else if (cstate == CS_VTIMER) { - lcd_outdezAtt(CSWONE_2ND_COLUMN, y, cs->v1+1, LEFT|attr); - v1_max = 99; - } - else { - putsMixerSource(CSWONE_2ND_COLUMN, y, cs->v1, attr); - } - if (attr) { - CHECK_INCDEC_MODELVAR(event, cs->v1, v1_min, v1_max); - } - break; - } - case CSW_FIELD_V2: - { - lcd_putsLeft(y, STR_V2); - int8_t v2_min=0, v2_max=MIXSRC_LAST_TELEM; - if (cstate == CS_VBOOL) { - putsSwitches(CSWONE_2ND_COLUMN, y, cs->v2, attr); - v2_min = SWSRC_OFF+1; v2_max = SWSRC_ON-1; - } - else if (cstate == CS_VTIMER) { - lcd_outdezAtt(CSWONE_2ND_COLUMN, y, cs->v2+1, LEFT|attr); - v2_max = 99; - } - else if (cstate == CS_VCOMP) { - putsMixerSource(CSWONE_2ND_COLUMN, y, cs->v2, attr); - } - else { -#if defined(FRSKY) - if (cs->v1 >= MIXSRC_FIRST_TELEM) { - putsTelemetryChannel(CSWONE_2ND_COLUMN, y, cs->v1 - MIXSRC_FIRST_TELEM, convertCswTelemValue(cs), attr|LEFT); - v2_max = maxTelemValue(cs->v1 - MIXSRC_FIRST_TELEM + 1); - if (cstate == CS_VOFS) { - v2_min = -128; - v2_max -= 128; - } - else { - v2_max = min((uint8_t)127, (uint8_t)v2_max); - v2_min = -v2_max; - } - if (cs->v2 > v2_max) { - cs->v2 = v2_max; - eeDirty(EE_MODEL); - } - } - else -#endif - { - v2_min = -125; v2_max = 125; - lcd_outdezAtt(CSWONE_2ND_COLUMN, y, cs->v2, LEFT|attr); - } - } - - if (attr) { - CHECK_INCDEC_MODELVAR(event, cs->v2, v2_min, v2_max); - } - break; - } - case CSW_FIELD_ANDSW: - lcd_putsLeft(y, STR_AND_SWITCH); - putsSwitches(CSWONE_2ND_COLUMN, y, cs->andsw, attr); - if (attr) CHECK_INCDEC_MODELVAR(event, cs->andsw, -MAX_SWITCH, MAX_SWITCH); - break; - case CSW_FIELD_DURATION: - lcd_putsLeft(y, STR_DURATION); - if (cs->duration > 0) - lcd_outdezAtt(CSWONE_2ND_COLUMN, y, 5*cs->duration, attr|PREC1|LEFT); - else - lcd_putsiAtt(CSWONE_2ND_COLUMN, y, STR_MMMINV, 0, attr); - if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, cs->duration, MAX_CSW_DURATION); - break; - case CSW_FIELD_DELAY: - lcd_putsLeft(y, STR_DELAY); - if (cs->delay > 0) - lcd_outdezAtt(CSWONE_2ND_COLUMN, y, 5*cs->delay, attr|PREC1|LEFT); - else - lcd_putsiAtt(CSWONE_2ND_COLUMN, y, STR_MMMINV, 0, attr); - if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, cs->delay, MAX_CSW_DELAY); - break; - } - } -} - -void menuModelCustomSwitches(uint8_t event) -{ - SIMPLE_MENU(STR_MENUCUSTOMSWITCHES, menuTabModel, e_CustomSwitches, NUM_CSW+1); - - uint8_t y = 0; - uint8_t k = 0; - int8_t sub = m_posVert - 1; - - switch (event) { -#if defined(ROTARY_ENCODER_NAVIGATION) - case EVT_ROTARY_BREAK: -#endif - case EVT_KEY_FIRST(KEY_RIGHT): - case EVT_KEY_FIRST(KEY_ENTER): - if (sub >= 0) { - s_currIdx = sub; - pushMenu(menuModelCustomSwitchOne); - } - break; - } - - for (uint8_t i=0; ifunc > 0) { - // CSW func - lcd_putsiAtt(CSW_1ST_COLUMN, y, STR_VCSWFUNC, cs->func, 0); - - // CSW params - uint8_t cstate = cswFamily(cs->func); - - if (cstate == CS_VBOOL) { - putsSwitches(CSW_2ND_COLUMN, y, cs->v1, 0); - putsSwitches(CSW_3RD_COLUMN, y, cs->v2, 0); - } - else if (cstate == CS_VCOMP) { - putsMixerSource(CSW_2ND_COLUMN, y, cs->v1, 0); - putsMixerSource(CSW_3RD_COLUMN, y, cs->v2, 0); - } - else if (cstate == CS_VTIMER) { - lcd_outdezAtt(CSW_2ND_COLUMN, y, cs->v1+1, LEFT); - lcd_outdezAtt(CSW_3RD_COLUMN, y, cs->v2+1, LEFT); - } - else { - putsMixerSource(CSW_2ND_COLUMN, y, cs->v1, 0); - if (cs->v1 >= MIXSRC_FIRST_TELEM) { - putsTelemetryChannel(CSW_3RD_COLUMN, y, cs->v1 - MIXSRC_FIRST_TELEM, convertCswTelemValue(cs), LEFT); - } - else { - lcd_outdezAtt(CSW_3RD_COLUMN, y, cs->v2, LEFT); - } - } - - // CSW and switch - putsSwitches(CSW_4TH_COLUMN, y, cs->andsw, 0); - } - } -} - -#else - -#if defined(PCBTARANIS) -enum ClipboardType { - CLIPBOARD_TYPE_NONE, - CLIPBOARD_TYPE_CUSTOM_SWITCH, - CLIPBOARD_TYPE_CUSTOM_FUNCTION, -}; - -struct Clipboard { - ClipboardType type; - union { - CustomSwData csw; - CustomFnData cfn; - } data; -}; - -Clipboard clipboard; - -void onCustomSwitchesMenu(const char *result) -{ - int8_t sub = m_posVert-1; - CustomSwData * cs = cswAddress(sub); - - if (result == STR_COPY) { - clipboard.type = CLIPBOARD_TYPE_CUSTOM_SWITCH; - clipboard.data.csw = *cs; - } - else if (result == STR_PASTE) { - *cs = clipboard.data.csw; - eeDirty(EE_MODEL); - } - else if (result == STR_DELETE) { - memset(cs, 0, sizeof(CustomSwData)); - eeDirty(EE_MODEL); - } -} -#endif - -void menuModelCustomSwitches(uint8_t event) -{ - INCDEC_DECLARE_VARS(); - - MENU(STR_MENUCUSTOMSWITCHES, menuTabModel, e_CustomSwitches, NUM_CSW+1, {0, NAVIGATION_LINE_BY_LINE|CSW_FIELD_LAST/*repeated...*/}); - - uint8_t y = 0; - uint8_t k = 0; - int8_t sub = m_posVert - 1; - horzpos_t horz = m_posHorz; - -#if LCD_W >= 212 - if (horz>=0) { - displayColumnHeader(STR_CSW_HEADERS, horz); - } -#endif - -#if defined(PCBTARANIS) - if (sub>=0 && horz<0 && event==EVT_KEY_LONG(KEY_ENTER) && !READ_ONLY()) { - killEvents(event); - CustomSwData * cs = cswAddress(sub); - if (cs->func) MENU_ADD_ITEM(STR_COPY); - if (clipboard.type == CLIPBOARD_TYPE_CUSTOM_SWITCH) - MENU_ADD_ITEM(STR_PASTE); - if (cs->func || cs->v1 || cs->v2 || cs->delay || cs->duration || cs->andsw) MENU_ADD_ITEM(STR_DELETE); - menuHandler = onCustomSwitchesMenu; - } -#endif - - for (uint8_t i=0; i0) ? BLINK|INVERS : INVERS) : 0); - uint8_t attr1 = (horz==1 ? attr : 0); - uint8_t attr2 = (horz==2 ? attr : 0); - CustomSwData * cs = cswAddress(k); - - // CSW name - uint8_t sw = SWSRC_SW1+k; - putsSwitches(0, y, sw, (getSwitch(sw) ? BOLD : 0) | ((sub==k && horz<0) ? INVERS : 0)); - - // CSW func - lcd_putsiAtt(CSW_1ST_COLUMN, y, STR_VCSWFUNC, cs->func, horz==0 ? attr : 0); - - // CSW params - uint8_t cstate = cswFamily(cs->func); -#if defined(CPUARM) - int16_t v1_min=0, v1_max=MIXSRC_LAST_TELEM, v2_min=0, v2_max=MIXSRC_LAST_TELEM; -#else - int8_t v1_min=0, v1_max=MIXSRC_LAST_TELEM, v2_min=0, v2_max=MIXSRC_LAST_TELEM; -#endif - - if (cstate == CS_VBOOL) { - putsSwitches(CSW_2ND_COLUMN, y, cs->v1, attr1); - putsSwitches(CSW_3RD_COLUMN, y, cs->v2, attr2); - v1_min = SWSRC_OFF+1; v1_max = SWSRC_ON-1; - v2_min = SWSRC_OFF+1; v2_max = SWSRC_ON-1; - INCDEC_SET_FLAG(INCDEC_SWITCH); - INCDEC_ENABLE_CHECK(NULL); - } - else if (cstate == CS_VCOMP) { - putsMixerSource(CSW_2ND_COLUMN, y, cs->v1, attr1); - putsMixerSource(CSW_3RD_COLUMN, y, cs->v2, attr2); - INCDEC_SET_FLAG(INCDEC_SOURCE); - INCDEC_ENABLE_CHECK(isSourceAvailable); - } - else if (cstate == CS_VTIMER) { - lcd_outdezAtt(CSW_2ND_COLUMN, y, cswTimerValue(cs->v1), LEFT|PREC1|attr1); - lcd_outdezAtt(CSW_3RD_COLUMN, y, cswTimerValue(cs->v2), LEFT|PREC1|attr2); - v1_min = v2_min = -128; - v1_max = v2_max = 122; - INCDEC_SET_FLAG(0); - INCDEC_ENABLE_CHECK(NULL); - } - else { - putsMixerSource(CSW_2ND_COLUMN, y, cs->v1, attr1); - if (horz == 1) { - INCDEC_SET_FLAG(INCDEC_SOURCE); - INCDEC_ENABLE_CHECK(isSourceAvailable); - } - else { - INCDEC_SET_FLAG(0); - INCDEC_ENABLE_CHECK(NULL); - } -#if defined(FRSKY) - if (cs->v1 >= MIXSRC_FIRST_TELEM) { - putsTelemetryChannel(CSW_3RD_COLUMN, y, cs->v1 - MIXSRC_FIRST_TELEM, convertCswTelemValue(cs), LEFT|attr2); - v2_max = maxTelemValue(cs->v1 - MIXSRC_FIRST_TELEM + 1); -#if defined(CPUARM) - v2_min = minTelemValue(cs->v1 - MIXSRC_FIRST_TELEM + 1); - if (cs->v2 < v2_min || cs->v2 > v2_max) { - cs->v2 = 0; - eeDirty(EE_MODEL); - } -#else - if (cstate == CS_VOFS) { - v2_min = -128; - v2_max -= 128; - } - else { - v2_max = min((uint8_t)127, (uint8_t)v2_max); - v2_min = -v2_max; - } - if (cs->v2 > v2_max) { - cs->v2 = v2_max; - eeDirty(EE_MODEL); - } -#endif - } - else { - lcd_outdezAtt(CSW_3RD_COLUMN, y, cs->v2, LEFT|attr2); - v2_min = -125; v2_max = 125; - } -#else - if (cs->v1 >= MIXSRC_FIRST_TELEM) { - putsTelemetryChannel(CSW_3RD_COLUMN, y, cs->v1 - MIXSRC_FIRST_TELEM, convertCswTelemValue(cs), LEFT|attr2); - v2_min = -128; v2_max = 127; - } - else { - lcd_outdezAtt(CSW_3RD_COLUMN, y, cs->v2, LEFT|attr2); - v2_min = -125; v2_max = 125; - } -#endif - } - - // CSW and switch - putsSwitches(CSW_4TH_COLUMN, y, cs->andsw, horz==3 ? attr : 0); - -#if defined(CPUARM) - // CSW duration - if (cs->duration > 0) - lcd_outdezAtt(CSW_5TH_COLUMN, y, 5*cs->duration, (horz==4 ? attr : 0)|PREC1|LEFT); - else - lcd_putsiAtt(CSW_5TH_COLUMN, y, STR_MMMINV, 0, horz==4 ? attr : 0); - - // CSW delay - if (cs->delay > 0) - lcd_outdezAtt(CSW_6TH_COLUMN, y, 5*cs->delay, (horz==5 ? attr : 0)|PREC1|LEFT); - else - lcd_putsiAtt(CSW_6TH_COLUMN, y, STR_MMMINV, 0, horz==5 ? attr : 0); -#endif - - if ((s_editMode>0 || p1valdiff) && attr) { - switch (horz) { - case CSW_FIELD_FUNCTION: - { - CHECK_INCDEC_MODELVAR_ZERO(event, cs->func, CS_MAXF); - uint8_t new_cstate = cswFamily(cs->func); - if (cstate != new_cstate) - cs->v1 = cs->v2 = (new_cstate==CS_VTIMER ? -119/*1.0*/ : 0); - break; - } - case CSW_FIELD_V1: - cs->v1 = CHECK_INCDEC_PARAM(event, cs->v1, v1_min, v1_max); - break; - case CSW_FIELD_V2: - cs->v2 = CHECK_INCDEC_PARAM(event, cs->v2, v2_min, v2_max); -#if defined(PCBTARANIS) - if (cstate==CS_VOFS && cs->v1!=0 && event==EVT_KEY_LONG(KEY_ENTER)) { - killEvents(event); - getvalue_t x = getValue(cs->v1); - TRACE("AUTO x=%d", x); - if (cs->v1 < MIXSRC_GVAR1) - cs->v2 = calcRESXto100(x); - else if (cs->v1 - MIXSRC_FIRST_TELEM + 1 == TELEM_ALT) - cs->v2 *= 100; - eeDirty(EE_MODEL); - } -#endif - break; - case CSW_FIELD_ANDSW: -#if defined(CPUARM) - CHECK_INCDEC_MODELSWITCH(event, cs->andsw, -MAX_CSW_ANDSW, MAX_CSW_ANDSW); -#else - CHECK_INCDEC_MODELVAR_ZERO(event, cs->andsw, MAX_CSW_ANDSW); -#endif - break; -#if defined(CPUARM) - case CSW_FIELD_DURATION: - CHECK_INCDEC_MODELVAR_ZERO(event, cs->duration, MAX_CSW_DURATION); - break; - case CSW_FIELD_DELAY: - CHECK_INCDEC_MODELVAR_ZERO(event, cs->delay, MAX_CSW_DELAY); - break; -#endif - } - } - } -} -#endif - -#if LCD_W >= 212 - #define MODEL_CUSTOM_FUNC_1ST_COLUMN (5+4*FW) - #define MODEL_CUSTOM_FUNC_2ND_COLUMN (9*FW) - #define MODEL_CUSTOM_FUNC_3RD_COLUMN (21*FW) - #define MODEL_CUSTOM_FUNC_4TH_COLUMN (33*FW-3) - #define MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF (34*FW-3) -#else - #define MODEL_CUSTOM_FUNC_1ST_COLUMN (3) - #define MODEL_CUSTOM_FUNC_2ND_COLUMN (5*FW-2) - #define MODEL_CUSTOM_FUNC_3RD_COLUMN (15*FW+2) - #define MODEL_CUSTOM_FUNC_4TH_COLUMN (20*FW) - #if defined(GRAPHICS) - #define MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF (20*FW) - #else - #define MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF (18*FW+2) - #endif -#endif - -#if defined(CPUARM) && defined(SDCARD) -void onCustomFunctionsFileSelectionMenu(const char *result) -{ - int8_t sub = m_posVert - 1; - - if (result == STR_UPDATE_LIST) { - char directory[] = SOUNDS_PATH; - strncpy(directory+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2); - if (!listSdFiles(directory, SOUNDS_EXT, sizeof(g_model.funcSw[sub].param), NULL)) { - POPUP_WARNING(STR_NO_SOUNDS_ON_SD); - s_menu_flags = 0; - } - } - else { - // The user choosed a wav file in the list - memcpy(g_model.funcSw[sub].param.name, result, sizeof(g_model.funcSw[sub].param.name)); - eeDirty(EE_MODEL); - } -} -#endif - -#if defined(PCBTARANIS) -void onCustomFunctionsMenu(const char *result) -{ - int8_t sub = m_posVert-1; - CustomFnData * cfn = &g_model.funcSw[sub]; - - if (result == STR_COPY) { - clipboard.type = CLIPBOARD_TYPE_CUSTOM_FUNCTION; - clipboard.data.cfn = *cfn; - } - else if (result == STR_PASTE) { - *cfn = clipboard.data.cfn; - eeDirty(EE_MODEL); - } - else if (result == STR_CLEAR) { - memset(cfn, 0, sizeof(CustomFnData)); - eeDirty(EE_MODEL); - } - else if (result == STR_INSERT) { - memmove(cfn+1, cfn, (NUM_CFN-sub-1)*sizeof(CustomFnData)); - memset(cfn, 0, sizeof(CustomFnData)); - eeDirty(EE_MODEL); - } - else if (result == STR_DELETE) { - memmove(cfn, cfn+1, (NUM_CFN-sub-1)*sizeof(CustomFnData)); - memset(&g_model.funcSw[NUM_CFN-1], 0, sizeof(CustomFnData)); - eeDirty(EE_MODEL); - } -} - -#endif - -void menuModelCustomFunctions(uint8_t event) -{ - MENU(STR_MENUCUSTOMFUNC, menuTabModel, e_CustomFunctions, NUM_CFN+1, {0, NAVIGATION_LINE_BY_LINE|3/*repeated*/}); - - uint8_t y; - uint8_t k = 0; - int8_t sub = m_posVert - 1; - -#if defined(PCBTARANIS) - if (sub>=0 && m_posHorz<0 && event==EVT_KEY_LONG(KEY_ENTER) && !READ_ONLY()) { - killEvents(event); - CustomFnData *sd = &g_model.funcSw[sub]; - if (!CFN_EMPTY(sd)) - MENU_ADD_ITEM(STR_COPY); - if (clipboard.type == CLIPBOARD_TYPE_CUSTOM_FUNCTION) - MENU_ADD_ITEM(STR_PASTE); - if (!CFN_EMPTY(sd) && CFN_EMPTY(&g_model.funcSw[NUM_CFN-1])) - MENU_ADD_ITEM(STR_INSERT); - if (CFN_EMPTY(sd)) - MENU_ADD_ITEM(STR_DELETE); - else - MENU_ADD_ITEM(STR_CLEAR); - menuHandler = onCustomFunctionsMenu; - } -#endif - - for (uint8_t i=0; i= 212 - putsStrIdx(0, y, STR_CF, k+1, (sub==k && m_posHorz<0) ? INVERS : 0); -#endif - - CustomFnData *sd = &g_model.funcSw[k]; - for (uint8_t j=0; j<4; j++) { - uint8_t attr = ((sub==k && m_posHorz==j) ? ((s_editMode>0) ? BLINK|INVERS : INVERS) : 0); - uint8_t active = (attr && (s_editMode>0 || p1valdiff)); - switch (j) { - case 0: - putsSwitches(MODEL_CUSTOM_FUNC_1ST_COLUMN, y, sd->swtch, attr | ((activeFnSwitches & ((MASK_CFN_TYPE)1 << k)) ? BOLD : 0)); - if (active || AUTOSWITCH_ENTER_LONG()) CHECK_INCDEC_MODELSWITCH(event, sd->swtch, SWSRC_FIRST, SWSRC_LAST); - break; - - case 1: - if (sd->swtch) { - uint8_t func_displayed; - if (CFN_FUNC(sd) < FUNC_TRAINER) { - func_displayed = 0; - putsChn(MODEL_CUSTOM_FUNC_2ND_COLUMN+6*FW, y, CFN_CH_NUMBER(sd)+1, attr); - } - else if (CFN_FUNC(sd) <= FUNC_TRAINER + NUM_STICKS) { - func_displayed = 1; - if (CFN_FUNC(sd) != FUNC_TRAINER) - putsMixerSource(MODEL_CUSTOM_FUNC_2ND_COLUMN+7*FW, y, MIXSRC_Rud+CFN_FUNC(sd)-FUNC_TRAINER-1, attr); - } -#if defined(DEBUG) - else if (CFN_FUNC(sd) == FUNC_TEST) { -#if defined(GVARS) - func_displayed = FUNC_TEST - FUNC_TRAINER - NUM_STICKS - MAX_GVARS + 2; -#else - func_displayed = FUNC_TEST - FUNC_TRAINER - NUM_STICKS + 1; -#endif - } -#endif -#if defined(GVARS) - else if (CFN_FUNC(sd) >= FUNC_ADJUST_GV1) { - func_displayed = FUNC_ADJUST_GV1 - FUNC_TRAINER - NUM_STICKS + 1; - putsStrIdx(MODEL_CUSTOM_FUNC_2ND_COLUMN+7*FW, y, STR_GV, CFN_FUNC(sd)-FUNC_ADJUST_GV1+1, attr); - } -#endif - else { - func_displayed = 2 + CFN_FUNC(sd) - FUNC_TRAINER - NUM_STICKS - 1; - } - lcd_putsiAtt(MODEL_CUSTOM_FUNC_2ND_COLUMN, y, STR_VFSWFUNC, func_displayed, attr); - if (active) { -#if defined(CPUARM) - CHECK_INCDEC_MODELVAR_ZERO(event, CFN_FUNC(sd), FUNC_MAX-1); -#else - if (CFN_FUNC(sd) < FUNC_TRAINER) { - CHECK_INCDEC_MODELVAR_ZERO(event, sd->internal.func_safety.func, 16); - } - else { - CHECK_INCDEC_MODELVAR_ZERO(event, CFN_FUNC(sd), FUNC_MAX-1); - if (CFN_FUNC(sd) < FUNC_TRAINER) - sd->internal.func_safety.func = 15; - } -#endif - if (checkIncDec_Ret) CFN_RESET(sd); - } - } - else if (attr) { - REPEAT_LAST_CURSOR_MOVE(); - } - break; - - case 2: - if (sd->swtch) { - INCDEC_DECLARE_VARS(); - int16_t val_displayed = CFN_PARAM(sd); - int8_t val_min = 0; - uint8_t val_max = 255; - if (CFN_FUNC(sd) == FUNC_PLAY_SOUND) { -#if defined(AUDIO) - val_max = AU_FRSKY_LAST-AU_FRSKY_FIRST-1; - lcd_putsiAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, STR_FUNCSOUNDS, val_displayed, attr); -#else - break; -#endif - } -#if defined(HAPTIC) - else if (CFN_FUNC(sd) == FUNC_HAPTIC) { - val_max = 3; - lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr|LEFT); - } -#endif -#if defined(CPUARM) && defined(SDCARD) - else if (CFN_FUNC(sd) == FUNC_PLAY_TRACK || CFN_FUNC(sd) == FUNC_BACKGND_MUSIC) { -#if LCD_W >= 212 - xcoord_t x = MODEL_CUSTOM_FUNC_3RD_COLUMN; -#else - xcoord_t x = (CFN_FUNC(sd) == FUNC_PLAY_TRACK ? MODEL_CUSTOM_FUNC_2ND_COLUMN + FW + FW*strlen(TR_PLAY_TRACK) : MODEL_CUSTOM_FUNC_3RD_COLUMN); -#endif - if (ZEXIST(sd->param.name)) - lcd_putsnAtt(x, y, sd->param.name, sizeof(sd->param.name), attr); - else - lcd_putsiAtt(x, y, STR_VCSWFUNC, 0, attr); - if (active && event==EVT_KEY_BREAK(KEY_ENTER)) { - s_editMode = 0; - char directory[] = SOUNDS_PATH; - strncpy(directory+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2); - if (listSdFiles(directory, SOUNDS_EXT, sizeof(sd->param.name), sd->param.name)) { - menuHandler = onCustomFunctionsFileSelectionMenu; - } - else { - POPUP_WARNING(STR_NO_SOUNDS_ON_SD); - s_menu_flags = 0; - } - } - break; - } - else if (CFN_FUNC(sd) == FUNC_PLAY_VALUE) { - val_max = MIXSRC_FIRST_TELEM + TELEM_DISPLAY_MAX - 1; - putsMixerSource(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr); - INCDEC_ENABLE_CHECK(isSourceAvailable); - } -#endif -#if defined(CPUARM) - else if (CFN_FUNC(sd) == FUNC_VOLUME) { - val_max = MIXSRC_LAST_CH; - putsMixerSource(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr); - INCDEC_ENABLE_CHECK(isSourceAvailable); - } -#elif defined(VOICE) - else if (CFN_FUNC(sd) == FUNC_PLAY_TRACK) { -#if defined(GVARS) - if (attr && event==EVT_KEY_LONG(KEY_ENTER)) { - killEvents(event); - s_editMode = !s_editMode; - active = true; - val_displayed = (val_displayed > 250 ? 0 : 251); - } - if (val_displayed > 250) { - putsStrIdx(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, STR_GV, val_displayed-250, attr); - } - else { - lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed+PROMPT_CUSTOM_BASE, attr|LEFT); - } -#else - lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed+PROMPT_CUSTOM_BASE, attr|LEFT); -#endif - } - else if (CFN_FUNC(sd) == FUNC_PLAY_BOTH) { - lcd_putcAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN+3*FWNUM, y, '|', attr); - lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN+3*FWNUM, y, val_displayed+PROMPT_CUSTOM_BASE, attr); - lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN+2+3*FWNUM, y, (val_displayed+PROMPT_CUSTOM_BASE+1)%10, attr|LEFT); - } - else if (CFN_FUNC(sd) == FUNC_PLAY_VALUE) { - val_max = MIXSRC_FIRST_TELEM + TELEM_DISPLAY_MAX - 1; - putsMixerSource(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr); - INCDEC_ENABLE_CHECK(isSourceAvailable); - } -#endif -#if defined(SDCARD) - else if (CFN_FUNC(sd) == FUNC_LOGS) { - if (val_displayed) { - lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr|PREC1|LEFT); - lcd_putc(lcdLastPos, y, 's'); - } - else { - lcd_putsiAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, STR_MMMINV, 0, attr); - } - } -#endif - else if (CFN_FUNC(sd) == FUNC_RESET) { - val_max = FUNC_RESET_PARAM_LAST; - lcd_putsiAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, STR_VFSWRESET, CFN_PARAM(sd), attr); - } - else if (CFN_FUNC(sd) < FUNC_TRAINER) { - val_displayed = (int8_t)CFN_PARAM(sd); - val_min = -125; val_max = 125; - lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr|LEFT); - } -#if defined(GVARS) - else if (CFN_FUNC(sd) >= FUNC_ADJUST_GV1 -#if defined(DEBUG) - && CFN_FUNC(sd) <= FUNC_ADJUST_GVLAST -#endif - ) { - switch (CFN_GVAR_MODE(sd)) { - case FUNC_ADJUST_GVAR_CONSTANT: - val_displayed = (int8_t)CFN_PARAM(sd); - val_min = -125; val_max = 125; - lcd_outdezAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr|LEFT); - break; - case FUNC_ADJUST_GVAR_SOURCE: - val_max = MIXSRC_LAST_CH; - putsMixerSource(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, val_displayed, attr); - INCDEC_ENABLE_CHECK(isSourceAvailable); - break; - case FUNC_ADJUST_GVAR_GVAR: - val_max = MAX_GVARS-1; - putsStrIdx(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, STR_GV, val_displayed+1, attr); - break; - default: // FUNC_ADJUST_GVAR_INC - val_max = 1; - lcd_putsiAtt(MODEL_CUSTOM_FUNC_3RD_COLUMN, y, PSTR("\002-1+1"), val_displayed, attr); - break; - } - - if (attr && event==EVT_KEY_LONG(KEY_ENTER)) { - killEvents(event); - s_editMode = !s_editMode; - active = true; - CFN_GVAR_MODE(sd) += 1; - val_displayed = 0; - } - } -#endif - else { - if (attr) m_posHorz = (CURSOR_MOVED_LEFT(event) ? 1 : 3); - break; - } - - if (active) { - CFN_PARAM(sd) = CHECK_INCDEC_PARAM(event, val_displayed, val_min, val_max); - } - } - else if (attr) { - REPEAT_LAST_CURSOR_MOVE(); - } - break; - - case 3: - if (sd->swtch && (CFN_FUNC(sd) <= FUNC_INSTANT_TRIM -#if defined(GVARS) - || CFN_FUNC(sd) >= FUNC_ADJUST_GV1 -#endif -#if defined(CPUARM) - || CFN_FUNC(sd) == FUNC_VOLUME -#endif - )) { - menu_lcd_onoff(MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF, y, CFN_ACTIVE(sd), attr); - if (active) CHECK_INCDEC_MODELVAR_ZERO(event, CFN_ACTIVE(sd), 1); - } - else if (sd->swtch && HAS_REPEAT_PARAM(sd)) { - if (CFN_PLAY_REPEAT(sd) == 0) { -#if LCD_W >= 212 - lcd_putsAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN+2, y, "1x", attr); -#else - lcd_putcAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF+1, y, '-', attr); -#endif - } -#if defined(CPUARM) - else if (CFN_PLAY_REPEAT(sd) == CFN_PLAY_REPEAT_NOSTART) { -#if LCD_W >= 212 - lcd_putcAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN-2, y, '!', attr); - lcd_putsAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN+2, y, "1x", attr); -#else - lcd_putcAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN_ONOFF+1, y, '!', attr); -#endif - } -#endif - else { - lcd_outdezAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN+2+FW, y, CFN_PLAY_REPEAT(sd)*CFN_PLAY_REPEAT_MUL, attr); -#if LCD_W >= 212 - lcd_putcAtt(MODEL_CUSTOM_FUNC_4TH_COLUMN+2+FW, y, 's', attr); -#endif - } -#if defined(CPUARM) - if (active) CFN_PLAY_REPEAT(sd) = checkIncDecModel(event, CFN_PLAY_REPEAT(sd)==CFN_PLAY_REPEAT_NOSTART?-1:CFN_PLAY_REPEAT(sd), -1, 60/CFN_PLAY_REPEAT_MUL); -#else - if (active) CHECK_INCDEC_MODELVAR_ZERO(event, CFN_PLAY_REPEAT(sd), 60/CFN_PLAY_REPEAT_MUL); -#endif - } - else if (attr) { - REPEAT_LAST_CURSOR_MOVE(); - } - break; - } - } - } -} - -#if defined(LUA_MODEL_SCRIPTS) -void onModelCustomScriptMenu(const char *result) -{ - ScriptData &sd = g_model.scriptsData[s_currIdx]; - - if (result == STR_UPDATE_LIST) { - if (!listSdFiles(SCRIPTS_PATH, MIXES_EXT, sizeof(sd.file), NULL)) { - POPUP_WARNING(STR_NO_BITMAPS_ON_SD); - s_menu_flags = 0; - } - } - else { - // The user choosed a lua file in the list - copySelection(sd.file, result, sizeof(sd.file)); - memset(sd.inputs, 0, sizeof(sd.inputs)); - eeDirty(EE_MODEL); - LUA_LOAD_MODEL_SCRIPT(s_currIdx); - } -} - -enum menuModelCustomScriptItems { - ITEM_MODEL_CUSTOMSCRIPT_FILE, - ITEM_MODEL_CUSTOMSCRIPT_NAME, - ITEM_MODEL_CUSTOMSCRIPT_PARAMS_LABEL, -}; - -#define SCRIPT_ONE_2ND_COLUMN_POS (12*FW) -#define SCRIPT_ONE_3RD_COLUMN_POS (23*FW) - -void menuModelCustomScriptOne(uint8_t event) -{ - TITLE(STR_MENUCUSTOMSCRIPT); - - ScriptData &sd = g_model.scriptsData[s_currIdx]; - - putsStrIdx(lcdLastPos+FW, 0, "LUA", s_currIdx+1, 0); - - SUBMENU_NOTITLE(3+scriptInternalData[s_currIdx].inputsCount, { 0, 0, LABEL(inputs), 0/*repeated*/ }); - - int8_t sub = m_posVert; - - for (uint8_t k=0; k0 ? BLINK|INVERS : INVERS) : 0); - - if (i == ITEM_MODEL_CUSTOMSCRIPT_FILE) { - lcd_putsLeft(y, "Script"); - if (ZEXIST(sd.file) > 0) - lcd_putsnAtt(SCRIPT_ONE_2ND_COLUMN_POS, y, sd.file, sizeof(sd.file), attr); - else - lcd_putsiAtt(SCRIPT_ONE_2ND_COLUMN_POS, y, STR_VCSWFUNC, 0, attr); - if (attr && event==EVT_KEY_BREAK(KEY_ENTER) && !READ_ONLY()) { - s_editMode = 0; - if (listSdFiles(SCRIPTS_PATH, MIXES_EXT, sizeof(sd.file), sd.file, LIST_NONE_SD_FILE)) { - menuHandler = onModelCustomScriptMenu; - } - else { - POPUP_WARNING(STR_NO_SCRIPTS_ON_SD); - s_menu_flags = 0; - } - } - } - else if (i == ITEM_MODEL_CUSTOMSCRIPT_NAME) { - lcd_putsLeft(y, "Name"); - editName(SCRIPT_ONE_2ND_COLUMN_POS, y, sd.name, sizeof(sd.name), event, attr); - } - else if (i == ITEM_MODEL_CUSTOMSCRIPT_PARAMS_LABEL) { - lcd_putsLeft(y, "Inputs"); - } - else if (i <= ITEM_MODEL_CUSTOMSCRIPT_PARAMS_LABEL+scriptInternalData[s_currIdx].inputsCount) { - int inputIdx = i-ITEM_MODEL_CUSTOMSCRIPT_PARAMS_LABEL-1; - lcd_putsnAtt(INDENT_WIDTH, y, scriptInternalData[s_currIdx].inputs[inputIdx].name, 10, 0); - if (scriptInternalData[s_currIdx].inputs[inputIdx].type == 0) { - lcd_outdezAtt(SCRIPT_ONE_2ND_COLUMN_POS, y, g_model.scriptsData[s_currIdx].inputs[inputIdx]+scriptInternalData[s_currIdx].inputs[inputIdx].def, attr|LEFT); - if (attr) { - CHECK_INCDEC_MODELVAR(event, g_model.scriptsData[s_currIdx].inputs[inputIdx], scriptInternalData[s_currIdx].inputs[inputIdx].min-scriptInternalData[s_currIdx].inputs[inputIdx].def, scriptInternalData[s_currIdx].inputs[inputIdx].max-scriptInternalData[s_currIdx].inputs[inputIdx].def); - } - } - else { - putsMixerSource(SCRIPT_ONE_2ND_COLUMN_POS, y, g_model.scriptsData[s_currIdx].inputs[inputIdx]+scriptInternalData[s_currIdx].inputs[inputIdx].def, attr); - if (attr) { - uint8_t *source = (uint8_t *)&g_model.scriptsData[s_currIdx].inputs[inputIdx]; - CHECK_INCDEC_MODELSOURCE(event, *source, scriptInternalData[s_currIdx].inputs[inputIdx].min-scriptInternalData[s_currIdx].inputs[inputIdx].def, scriptInternalData[s_currIdx].inputs[inputIdx].max-scriptInternalData[s_currIdx].inputs[inputIdx].def); - } - } - } - } - - if (scriptInternalData[s_currIdx].outputsCount > 0) { - lcd_vline(SCRIPT_ONE_3RD_COLUMN_POS-4, FH+1, LCD_H-FH-1); - lcd_puts(SCRIPT_ONE_3RD_COLUMN_POS, FH+1, "Outputs"); - - for (int i=0; i= 0) { - s_currIdx = sub; - pushMenu(menuModelCustomScriptOne); - } - break; - } - - for (int i=0; i= 212 - #define TELEM_COL1 (1*FW) - #define TELEM_COL2 (16*FW) - #define TELEM_COL3 (28*FW) - #define TELEM_BARS_COLMIN (3*FW+56) - #define TELEM_BARS_COLMAX (20*FW-3) - #define TELEM_SCRTYPE_COL (10*FW) -#else - #define TELEM_COL1 INDENT_WIDTH - #if defined(TRANSLATIONS_FR) || defined(TRANSLATIONS_CZ) - #define TELEM_COL2 (9*FW) - #else - #define TELEM_COL2 (8*FW) - #endif - #define TELEM_BARS_COLMIN (56-3*FW) - #define TELEM_BARS_COLMAX (14*FW-3) - #define TELEM_SCRTYPE_COL (10*FW) -#endif - -#if defined(PCBTARANIS) - #define CHANNEL_ROWS (uint8_t)-1, 1, 0, 0, 0, - #define RSSI_ROWS (uint8_t)-1, 0, 0, -#else - #define CHANNEL_ROWS (uint8_t)-1, 1, 0, 2, 2, - #define RSSI_ROWS (uint8_t)-1, 1, 1, -#endif - -#if defined(GAUGES) - #define SCREEN_TYPE_ROWS 0 -#else - #define SCREEN_TYPE_ROWS (uint8_t)-1 -#endif - -#if defined(PCBSTD) - #define VARIO_RANGE_ROWS 1 -#else - #define VARIO_RANGE_ROWS 3 -#endif - -void menuModelTelemetry(uint8_t event) -{ - MENU(STR_MENUTELEMETRY, menuTabModel, e_Telemetry, ITEM_TELEMETRY_MAX+1, {0, CHANNEL_ROWS CHANNEL_ROWS RSSI_ROWS USRDATA_LINES 0, 0, IF_CPUARM(0) IF_VARIO(LABEL(Vario)) IF_VARIO(0) IF_VARIO(VARIO_RANGE_ROWS) CASE_PCBTARANIS(LABEL(TopBar)) CASE_PCBTARANIS(0) SCREEN_TYPE_ROWS, 2, 2, 2, 2, SCREEN_TYPE_ROWS, 2, 2, 2, 2, IF_CPUARM(SCREEN_TYPE_ROWS) IF_CPUARM(2) IF_CPUARM(2) IF_CPUARM(2) IF_CPUARM(2) }); - - uint8_t sub = m_posVert - 1; - -#if !defined(PCBTARANIS) - switch (event) { - case EVT_KEY_BREAK(KEY_DOWN): - case EVT_KEY_BREAK(KEY_UP): - case EVT_KEY_BREAK(KEY_LEFT): - case EVT_KEY_BREAK(KEY_RIGHT): - if (s_editMode>0 && sub<=ITEM_TELEMETRY_RSSI_ALARM2) - frskySendAlarms(); // update FrSky module when edit mode exited - break; - } -#endif - - for (uint8_t i=0; i0) ? BLINK|INVERS : INVERS); - uint8_t attr = (sub == k ? blink : 0); - uint8_t ch = (k >= ITEM_TELEMETRY_A2_LABEL) ? 1 : 0; - FrSkyChannelData & channel = g_model.frsky.channels[ch]; - uint8_t dest=TELEM_A1-1+ch; - switch(k) { - case ITEM_TELEMETRY_A1_LABEL: - case ITEM_TELEMETRY_A2_LABEL: - lcd_putsLeft(y, STR_ACHANNEL); - lcd_outdezAtt(2*FW, y, ch+1, 0); - putsTelemetryChannel(TELEM_COL2+6*FW, y, dest, frskyData.analog[ch].value, LEFT); - break; - - case ITEM_TELEMETRY_A1_RANGE: - case ITEM_TELEMETRY_A2_RANGE: - lcd_putsLeft(y, STR_RANGE); - putsTelemetryChannel(TELEM_COL2, y, dest, 255-channel.offset, (m_posHorz<=0 ? attr : 0)|NO_UNIT|LEFT); - lcd_putsiAtt(lcdLastPos, y, STR_VTELEMUNIT, channel.type, m_posHorz!=0 ? attr : 0); - if (attr && (s_editMode>0 || p1valdiff)) { - if (m_posHorz == 0) { - uint16_t ratio = checkIncDec(event, channel.ratio, 0, 256, EE_MODEL); - if (checkIncDec_Ret) { - if (ratio == 127 && channel.multiplier > 0) { - channel.multiplier--; channel.ratio = 255; - } - else if (ratio == 256) { - if (channel.multiplier < FRSKY_MULTIPLIER_MAX) { channel.multiplier++; channel.ratio = 128; } - } - else { - channel.ratio = ratio; - } - } - } - else { - CHECK_INCDEC_MODELVAR_ZERO(event, channel.type, UNIT_A1A2_MAX); - } - } - break; - - case ITEM_TELEMETRY_A1_OFFSET: - case ITEM_TELEMETRY_A2_OFFSET: - lcd_putsLeft(y, STR_OFFSET); - putsTelemetryChannel(TELEM_COL2, y, dest, 0, LEFT|attr); - if (attr) channel.offset = checkIncDec(event, channel.offset, -256, 256, EE_MODEL); - break; - - case ITEM_TELEMETRY_A1_ALARM1: - case ITEM_TELEMETRY_A1_ALARM2: - case ITEM_TELEMETRY_A2_ALARM1: - case ITEM_TELEMETRY_A2_ALARM2: - { - uint8_t j = ((k==ITEM_TELEMETRY_A1_ALARM1 || k==ITEM_TELEMETRY_A2_ALARM1) ? 0 : 1); -#if defined(PCBTARANIS) - lcd_putsLeft(y, (j==0 ? STR_LOWALARM : STR_CRITICALALARM)); - putsTelemetryChannel(TELEM_COL2, y, dest, channel.alarms_value[j], LEFT|attr); - if (attr && (s_editMode>0 || p1valdiff)) { - channel.alarms_value[j] = checkIncDec(event, channel.alarms_value[j], 0, 255, EE_MODEL); - } -#else - lcd_putsLeft(y, STR_ALARM); - lcd_putsiAtt(TELEM_COL2, y, STR_VALARM, ALARM_LEVEL(ch, j), m_posHorz<=0 ? attr : 0); - lcd_putsiAtt(TELEM_COL2+4*FW, y, STR_VALARMFN, ALARM_GREATER(ch, j), (m_posHorz<0 || m_posHorz==1) ? attr : 0); - putsTelemetryChannel(TELEM_COL2+6*FW, y, dest, channel.alarms_value[j], ((m_posHorz<0 || m_posHorz==2) ? attr : 0) | LEFT); - - if (attr && (s_editMode>0 || p1valdiff)) { - uint8_t t; - switch (m_posHorz) { - case 0: - t = ALARM_LEVEL(ch, j); - channel.alarms_level = (channel.alarms_level & ~(3<<(2*j))) + (checkIncDecModel(event, t, 0, 3) << (2*j)); - break; - case 1: - t = ALARM_GREATER(ch, j); - if (t != checkIncDecModel(event, t, 0, 1)) { - channel.alarms_greater ^= (1 << j); - frskySendAlarms(); - } - break; - case 2: - channel.alarms_value[j] = checkIncDec(event, channel.alarms_value[j], 0, 255, EE_MODEL); - break; - } - } -#endif - break; - } - - case ITEM_TELEMETRY_RSSI_LABEL: - lcd_putsLeft(y, PSTR("RSSI")); - break; - - case ITEM_TELEMETRY_RSSI_ALARM1: - case ITEM_TELEMETRY_RSSI_ALARM2: { - uint8_t j = k-ITEM_TELEMETRY_RSSI_ALARM1; -#if defined(PCBTARANIS) - lcd_putsLeft(y, (j==0 ? STR_LOWALARM : STR_CRITICALALARM)); - lcd_outdezNAtt(TELEM_COL2, y, getRssiAlarmValue(j), LEFT|attr, 3); - if (attr && (s_editMode>0 || p1valdiff)) { - CHECK_INCDEC_MODELVAR(event, g_model.frsky.rssiAlarms[j].value, -30, 30); - } -#else - lcd_putsLeft(y, STR_ALARM); - lcd_putsiAtt(TELEM_COL2, y, STR_VALARM, ((2+j+g_model.frsky.rssiAlarms[j].level)%4), m_posHorz<=0 ? attr : 0); - lcd_putc(TELEM_COL2+4*FW, y, '<'); - lcd_outdezNAtt(TELEM_COL2+6*FW, y, getRssiAlarmValue(j), LEFT|(m_posHorz!=0 ? attr : 0), 3); - - if (attr && (s_editMode>0 || p1valdiff)) { - switch (m_posHorz) { - case 0: - CHECK_INCDEC_MODELVAR(event, g_model.frsky.rssiAlarms[j].level, -3, 2); // circular (saves flash) - break; - case 1: - CHECK_INCDEC_MODELVAR(event, g_model.frsky.rssiAlarms[j].value, -30, 30); - break; - } - } -#endif - break; - } - -#if defined(FRSKY_HUB) || defined(WS_HOW_HIGH) - case ITEM_TELEMETRY_USR_LABEL: - lcd_putsLeft(y, STR_USRDATA); - break; - -#if !defined(PCBTARANIS) - case ITEM_TELEMETRY_USR_PROTO: - lcd_putsLeft(y, STR_PROTO); - lcd_putsiAtt(TELEM_COL2, y, STR_VTELPROTO, g_model.frsky.usrProto, attr); - if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.usrProto, USR_PROTO_LAST); - break; -#endif - - case ITEM_TELEMETRY_USR_BLADES: - lcd_putsLeft(y, STR_BLADES); - lcd_outdezAtt(TELEM_COL2+FWNUM, y, 2+g_model.frsky.blades, attr); - if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.blades, 3); - break; -#endif - - case ITEM_TELEMETRY_USR_VOLTAGE_SOURCE: - lcd_putsLeft(y, STR_VOLTAGE); - lcd_putsiAtt(TELEM_COL2, y, STR_VOLTSRC, g_model.frsky.voltsSource+1, attr); - if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.voltsSource, 3); - break; - - case ITEM_TELEMETRY_USR_CURRENT_SOURCE: - lcd_putsLeft(y, STR_CURRENT); - lcd_putsiAtt(TELEM_COL2, y, STR_VOLTSRC, g_model.frsky.currentSource, attr); - if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.currentSource, 3); - break; - -#if defined(CPUARM) - case ITEM_TELEMTETRY_PERSISTENT_MAH: - g_model.frsky.mAhPersistent = onoffMenuItem(g_model.frsky.mAhPersistent, TELEM_COL2, y, STR_PERSISTENT_MAH, attr, event); - break; -#endif - -#if defined(VARIO) - case ITEM_TELEMETRY_VARIO_LABEL: - lcd_putsLeft(y, STR_VARIO); - break; - - case ITEM_TELEMETRY_VARIO_SOURCE: - lcd_putsLeft(y, STR_SOURCE); - lcd_putsiAtt(TELEM_COL2, y, STR_VARIOSRC, g_model.frsky.varioSource, attr); - if (attr) CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioSource, 0, VARIO_SOURCE_LAST); - break; - - case ITEM_TELEMETRY_VARIO_RANGE: - lcd_putsLeft(y, STR_LIMIT); -#if defined(PCBSTD) - lcd_outdezAtt(TELEM_COL2, y, 5+g_model.frsky.varioCenterMax, (m_posHorz==0 ? attr : 0)|PREC1|LEFT); - lcd_outdezAtt(TELEM_COL2+8*FW, y, 10+g_model.frsky.varioMax, (m_posHorz==1 ? attr : 0)); - if (attr && (s_editMode>0 || p1valdiff)) { - switch (m_posHorz) { - case 0: - CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioCenterMax, -15, +15); - break; - case 1: - CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioMax, -7, 7); - break; - } - } -#else - lcd_outdezAtt(TELEM_COL2, y, -10+g_model.frsky.varioMin, (m_posHorz<=0 ? attr : 0)|LEFT); - if (g_model.frsky.varioCenterMin == -16) - lcd_putsAtt(TELEM_COL2+4*FW-2, y, STR_OFF, m_posHorz==1 ? attr : 0); - else - lcd_outdezAtt(TELEM_COL2+7*FW-2, y, -5+g_model.frsky.varioCenterMin, ((m_posHorz<0 || m_posHorz==1) ? attr : 0)|PREC1); - lcd_outdezAtt(TELEM_COL2+10*FW, y, 5+g_model.frsky.varioCenterMax, ((m_posHorz<0 || m_posHorz==2) ? attr : 0)|PREC1); - lcd_outdezAtt(TELEM_COL2+13*FW+2, y, 10+g_model.frsky.varioMax, ((m_posHorz<0 || m_posHorz==3) ? attr : 0)); - if (attr && (s_editMode>0 || p1valdiff)) { - switch (m_posHorz) { - case 0: - CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioMin, -7, 7); - break; - case 1: - CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioCenterMin, -16, 5+min(10, g_model.frsky.varioCenterMax+5)); - break; - case 2: - CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioCenterMax, -5+max(-10, g_model.frsky.varioCenterMin-5), +15); - break; - case 3: - CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioMax, -7, 7); - break; - } - } -#endif - break; -#endif - -#if defined(PCBTARANIS) - case ITEM_TELEMETRY_TOP_BAR_LABEL: - lcd_putsLeft(y, STR_TOP_BAR); - break; - - case ITEM_TELEMETRY_TOP_BAR_ALTITUDE: - g_model.frsky.altitudeDisplayed = onoffMenuItem(g_model.frsky.altitudeDisplayed, TELEM_COL2, y, STR_ALTITUDE, attr, event); - break; -#endif - - case ITEM_TELEMETRY_SCREEN_LABEL1: - case ITEM_TELEMETRY_SCREEN_LABEL2: -#if defined(CPUARM) - case ITEM_TELEMETRY_SCREEN_LABEL3: - { - uint8_t screenIndex = (k < ITEM_TELEMETRY_SCREEN_LABEL2 ? 0 : (k < ITEM_TELEMETRY_SCREEN_LABEL3 ? 1 : 2)); - putsStrIdx(0*FW, y, STR_SCREEN, screenIndex+1); -#if defined(GAUGES) - bool screenType = IS_BARS_SCREEN(screenIndex); - if (screenType != selectMenuItem(TELEM_SCRTYPE_COL, y, PSTR(""), STR_VSCREEN, screenType, 0, 1, attr, event)) - g_model.frsky.screensType ^= (1 << screenIndex); -#endif - break; - } -#else - { - uint8_t screenIndex = (k < ITEM_TELEMETRY_SCREEN_LABEL2 ? 1 : 2); - putsStrIdx(0*FW, y, STR_SCREEN, screenIndex); -#if defined(GAUGES) - bool screenType = g_model.frsky.screensType & screenIndex; - if (screenType != selectMenuItem(TELEM_SCRTYPE_COL, y, PSTR(""), STR_VSCREEN, screenType, 0, 1, attr, event)) - g_model.frsky.screensType ^= screenIndex; -#endif - break; - } -#endif - - case ITEM_TELEMETRY_SCREEN_LINE1: - case ITEM_TELEMETRY_SCREEN_LINE2: - case ITEM_TELEMETRY_SCREEN_LINE3: - case ITEM_TELEMETRY_SCREEN_LINE4: - case ITEM_TELEMETRY_SCREEN_LINE5: - case ITEM_TELEMETRY_SCREEN_LINE6: - case ITEM_TELEMETRY_SCREEN_LINE7: - case ITEM_TELEMETRY_SCREEN_LINE8: - -#if defined(CPUARM) - case ITEM_TELEMETRY_SCREEN_LINE9: - case ITEM_TELEMETRY_SCREEN_LINE10: - case ITEM_TELEMETRY_SCREEN_LINE11: - case ITEM_TELEMETRY_SCREEN_LINE12: -#endif - - { - uint8_t screenIndex, lineIndex; - if (k < ITEM_TELEMETRY_SCREEN_LABEL2) { - screenIndex = 0; - lineIndex = k-ITEM_TELEMETRY_SCREEN_LINE1; - } -#if defined(CPUARM) - else if (k >= ITEM_TELEMETRY_SCREEN_LABEL3) { - screenIndex = 2; - lineIndex = k-ITEM_TELEMETRY_SCREEN_LINE9; - } -#endif - else { - screenIndex = 1; - lineIndex = k-ITEM_TELEMETRY_SCREEN_LINE5; - } - -#if 0 - putsStrIdx(0, y, PSTR(INDENT"Line"), lineIndex+1, m_posHorz<0 ? attr : 0); -#endif - -#if defined(GAUGES) - if (IS_BARS_SCREEN(screenIndex)) { - FrSkyBarData & bar = g_model.frsky.screens[screenIndex].bars[lineIndex]; - uint8_t barSource = bar.source; - lcd_putsiAtt(TELEM_COL1, y, STR_VTELEMCHNS, barSource, m_posHorz==0 ? attr : 0); - if (barSource) { - putsTelemetryChannel(TELEM_BARS_COLMIN, y, barSource-1, convertTelemValue(barSource, bar.barMin), (m_posHorz==1 ? attr : 0) | LEFT); - putsTelemetryChannel(TELEM_BARS_COLMAX, y, barSource-1, convertTelemValue(barSource, 255-bar.barMax), (m_posHorz==2 ? attr : 0) | LEFT); - } - else if (attr) { - MOVE_CURSOR_FROM_HERE(); - } - if (attr && (s_editMode>0 || p1valdiff)) { - switch (m_posHorz) { - case 0: - bar.source = checkIncDecModel(event, barSource, 0, TELEM_DISPLAY_MAX); - if (checkIncDec_Ret) { - bar.barMin = 0; - bar.barMax = 255-maxTelemValue(bar.source); - } - break; - case 1: - bar.barMin = checkIncDec(event, bar.barMin, 0, 254-bar.barMax, EE_MODEL|NO_INCDEC_MARKS); - break; - case 2: - bar.barMax = 255 - checkIncDec(event, 255-bar.barMax, bar.barMin+1, maxTelemValue(barSource), EE_MODEL|NO_INCDEC_MARKS); - break; - } - } - } - else -#endif - { - for (uint8_t c=0; c0 || p1valdiff)) { - CHECK_INCDEC_MODELVAR_ZERO(event, value, (lineIndex==3 && c==0) ? TELEM_STATUS_MAX : TELEM_DISPLAY_MAX); - } - } - if (attr && m_posHorz == NUM_LINE_ITEMS) { - REPEAT_LAST_CURSOR_MOVE(); - } - } - break; - } - } - } -} -#endif - -#if defined(TEMPLATES) -void menuModelTemplates(uint8_t event) -{ - SIMPLE_MENU(STR_MENUTEMPLATES, menuTabModel, e_Templates, 1+TMPL_COUNT); - - uint8_t sub = m_posVert - 1; - - if (sub < TMPL_COUNT) { - if (s_warning_result) { - s_warning_result = 0; - applyTemplate(sub); - AUDIO_WARNING2(); - } - if (event==EVT_KEY_BREAK(KEY_ENTER)) { - POPUP_CONFIRMATION(STR_VTEMPLATES+1 + (sub * LEN2_VTEMPLATES)); - s_editMode = 0; - } - } - - uint8_t y = 1 + 1*FH; - uint8_t k = 0; - for (uint8_t i=0; i frskyData.hub.maxRpm) diff --git a/radio/src/telemetry/frsky.cpp~ b/radio/src/telemetry/frsky.cpp~ deleted file mode 100644 index 35d3bf5cc..000000000 --- a/radio/src/telemetry/frsky.cpp~ +++ /dev/null @@ -1,926 +0,0 @@ -/* - * 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. - * - */ - -#include "../opentx.h" - -// Enumerate FrSky packet codes -#define LINKPKT 0xfe -#define USRPKT 0xfd -#define A11PKT 0xfc -#define A12PKT 0xfb -#define A21PKT 0xfa -#define A22PKT 0xf9 -#define ALRM_REQUEST 0xf8 -#define RSSI1PKT 0xf7 -#define RSSI2PKT 0xf6 -#define RSSI_REQUEST 0xf1 - -#define START_STOP 0x7e -#define BYTESTUFF 0x7d -#define STUFF_MASK 0x20 - -#if defined(TELEMETREZ) -#define PRIVATE 0x1B -#endif - -uint8_t frskyRxBuffer[FRSKY_RX_PACKET_SIZE]; // Receive buffer. 9 bytes (full packet), worst case 18 bytes with byte-stuffing (+1) -uint8_t frskyTxBuffer[FRSKY_TX_PACKET_SIZE]; // Ditto for transmit buffer -#if !defined(CPUARM) -uint8_t frskyTxBufferCount = 0; -#endif -uint8_t frskyStreaming = 0; -#if defined(WS_HOW_HIGH) -uint8_t frskyUsrStreaming = 0; -#endif -uint8_t link_counter = 0; -FrskyData frskyData; - -#if defined(FRSKY_HUB) || defined(WS_HOW_HIGH) -void checkMinMaxAltitude() -{ - if (TELEMETRY_ALT_BP > frskyData.hub.maxAltitude) - frskyData.hub.maxAltitude = TELEMETRY_ALT_BP; - if (TELEMETRY_ALT_BP < frskyData.hub.minAltitude) - frskyData.hub.minAltitude = TELEMETRY_ALT_BP; -} -#endif - -#if defined(VARIO) && !defined(FRSKY_SPORT) && (defined(FRSKY_HUB) || defined(WS_HOW_HIGH)) -void evalVario(int16_t altitude_bp, uint16_t altitude_ap) -{ - int32_t varioAltitude_cm = (int32_t)altitude_bp * 100 + (altitude_bp > 0 ? altitude_ap : -altitude_ap); - uint8_t varioAltitudeQueuePointer = frskyData.hub.varioAltitudeQueuePointer + 1; - if (varioAltitudeQueuePointer >= VARIO_QUEUE_LENGTH) - varioAltitudeQueuePointer = 0; - frskyData.hub.varioAltitudeQueuePointer = varioAltitudeQueuePointer; - frskyData.hub.varioSpeed -= frskyData.hub.varioAltitudeQueue[varioAltitudeQueuePointer] ; - frskyData.hub.varioAltitudeQueue[varioAltitudeQueuePointer] = varioAltitude_cm - frskyData.hub.varioAltitude_cm; - frskyData.hub.varioAltitude_cm = varioAltitude_cm; - frskyData.hub.varioSpeed += frskyData.hub.varioAltitudeQueue[varioAltitudeQueuePointer] ; -} -#else -#define evalVario(...) -#endif - -#if defined(FRSKY_HUB) -typedef enum { - TS_IDLE = 0, // waiting for 0x5e frame marker - TS_DATA_ID, // waiting for dataID - TS_DATA_LOW, // waiting for data low byte - TS_DATA_HIGH, // waiting for data high byte - TS_XOR = 0x80 // decode stuffed byte -} TS_STATE; - -void parseTelemHubByte(uint8_t byte) -{ - static int8_t structPos; - static uint8_t lowByte; - static TS_STATE state = TS_IDLE; - - if (byte == 0x5e) { - state = TS_DATA_ID; - return; - } - if (state == TS_IDLE) { - return; - } - if (state & TS_XOR) { - byte = byte ^ 0x60; - state = (TS_STATE)(state - TS_XOR); - } - if (byte == 0x5d) { - state = (TS_STATE)(state | TS_XOR); - return; - } - if (state == TS_DATA_ID) { - if (byte > 0x3f) { - state = TS_IDLE; - } - else { - structPos = byte*2; - state = TS_DATA_LOW; - } - return; - } - if (state == TS_DATA_LOW) { - lowByte = byte; - state = TS_DATA_HIGH; - return; - } - - state = TS_IDLE; - -#if defined(GPS) - if ((uint8_t)structPos == offsetof(FrskySerialData, gpsLatitude_bp)) { - if (lowByte || byte) - frskyData.hub.gpsFix = 1; - else if (frskyData.hub.gpsFix > 0 && frskyData.hub.gpsLatitude_bp > 1) - frskyData.hub.gpsFix = 0; - } - else if ((uint8_t)structPos == offsetof(FrskySerialData, gpsLongitude_bp)) { - if (lowByte || byte) - frskyData.hub.gpsFix = 1; - else if (frskyData.hub.gpsFix > 0 && frskyData.hub.gpsLongitude_bp > 1) - frskyData.hub.gpsFix = 0; - } - - if ((uint8_t)structPos == offsetof(FrskySerialData, gpsAltitude_bp) || - ((uint8_t)structPos >= offsetof(FrskySerialData, gpsAltitude_ap) && (uint8_t)structPos <= offsetof(FrskySerialData, gpsLatitudeNS) && (uint8_t)structPos != offsetof(FrskySerialData, baroAltitude_bp) && (uint8_t)structPos != offsetof(FrskySerialData, baroAltitude_ap))) { - // If we don't have a fix, we may discard the value - if (frskyData.hub.gpsFix <= 0) - return; - } -#endif - -#if 0 - uint16_t previousValue = *((uint16_t *)(((uint8_t*)&frskyData.hub) + structPos)); -#endif - - ((uint8_t*)&frskyData.hub)[structPos] = lowByte; - ((uint8_t*)&frskyData.hub)[structPos+1] = byte; - - switch ((uint8_t)structPos) { - - case offsetof(FrskySerialData, rpm): - //frskyData.hub.rpm *= (uint8_t)60/(g_model.frsky.blades+2); - // Change minimum Blades to 1 to allow for single sensors/raw data - T.Foley - // Added Spur and Pinion Ratio Calculation to provide final head/drive RPM after gearing - // - frskyData.hub.rpm *= (uint8_t)60; - frskyData.hub.rpm /= (g_model.frsky.blades+1); - float gear_ratio = (((float)g_model.frsky.spur_gear+1) / ((float)g_model.frsky.pinion_gear+1)); - frskyData.hub.rpm = (float)(frskyData.hub.rpm / gear_ratio); - if (frskyData.hub.rpm > frskyData.hub.maxRpm) - frskyData.hub.maxRpm = frskyData.hub.rpm; - break; - - case offsetof(FrskySerialData, temperature1): - if (frskyData.hub.temperature1 > frskyData.hub.maxTemperature1) - frskyData.hub.maxTemperature1 = frskyData.hub.temperature1; - break; - - case offsetof(FrskySerialData, temperature2): - if (frskyData.hub.temperature2 > frskyData.hub.maxTemperature2) - frskyData.hub.maxTemperature2 = frskyData.hub.temperature2; - break; - - case offsetof(FrskySerialData, current): - if (frskyData.hub.current > frskyData.hub.maxCurrent) - frskyData.hub.maxCurrent = frskyData.hub.current; - break; - - case offsetof(FrskySerialData, currentConsumption): - // we receive data from openXsensor. stops the calculation of consumption and power - frskyData.hub.openXsensor = 1; - break; - - case offsetof(FrskySerialData, volts_ap): -#if defined(FAS_BSS) - frskyData.hub.vfas = (frskyData.hub.volts_bp * 10 + frskyData.hub.volts_ap); -#else - frskyData.hub.vfas = ((frskyData.hub.volts_bp * 100 + frskyData.hub.volts_ap * 10) * 21) / 110; -#endif - /* TODO later if (!frskyData.hub.minVfas || frskyData.hub.minVfas > frskyData.hub.vfas) - frskyData.hub.minVfas = frskyData.hub.vfas; */ - break; - - case offsetof(FrskySerialData, baroAltitude_bp): - // First received barometer altitude => Altitude offset - if (!frskyData.hub.baroAltitudeOffset) - frskyData.hub.baroAltitudeOffset = -frskyData.hub.baroAltitude_bp; - if (g_model.frsky.varioSource == VARIO_SOURCE_ALTI) { - evalVario(frskyData.hub.baroAltitude_bp, 0); - } - frskyData.hub.baroAltitude_bp += frskyData.hub.baroAltitudeOffset; - checkMinMaxAltitude(); - break; - - case offsetof(FrskySerialData, baroAltitude_ap): - if (g_model.frsky.varioSource == VARIO_SOURCE_ALTI_PLUS) { - evalVario(frskyData.hub.baroAltitude_bp-frskyData.hub.baroAltitudeOffset, frskyData.hub.baroAltitude_ap); - } - break; - -#if defined(GPS) - case offsetof(FrskySerialData, gpsAltitude_ap): - if (!frskyData.hub.gpsAltitudeOffset) - frskyData.hub.gpsAltitudeOffset = -frskyData.hub.gpsAltitude_bp; - frskyData.hub.gpsAltitude_bp += frskyData.hub.gpsAltitudeOffset; - if (!frskyData.hub.baroAltitudeOffset) { - if (frskyData.hub.gpsAltitude_bp > frskyData.hub.maxAltitude) - frskyData.hub.maxAltitude = frskyData.hub.gpsAltitude_bp; - if (frskyData.hub.gpsAltitude_bp < frskyData.hub.minAltitude) - frskyData.hub.minAltitude = frskyData.hub.gpsAltitude_bp; - } - if (!frskyData.hub.pilotLatitude && !frskyData.hub.pilotLongitude) { - // First received GPS position => Pilot GPS position - getGpsPilotPosition(); - } - else if (frskyData.hub.gpsDistNeeded || g_menuStack[g_menuStackPtr] == menuTelemetryFrsky) { - getGpsDistance(); - } - break; - - case offsetof(FrskySerialData, gpsSpeed_bp): - // Speed => Max speed - if (frskyData.hub.gpsSpeed_bp > frskyData.hub.maxGpsSpeed) - frskyData.hub.maxGpsSpeed = frskyData.hub.gpsSpeed_bp; - break; -#endif - - case offsetof(FrskySerialData, volts): - // Voltage => Cell number + Cell voltage - { - uint8_t battnumber = ((frskyData.hub.volts & 0x00F0) >> 4); - if (battnumber < 12) { - if (frskyData.hub.cellsCount < battnumber+1) { - frskyData.hub.cellsCount = battnumber+1; - } - uint8_t cellVolts = (uint8_t)(((((frskyData.hub.volts & 0xFF00) >> 8) + ((frskyData.hub.volts & 0x000F) << 8)))/10); - frskyData.hub.cellVolts[battnumber] = cellVolts; - if (!frskyData.hub.minCellVolts || cellVolts < frskyData.hub.minCellVolts || battnumber==frskyData.hub.minCellIdx) { - frskyData.hub.minCellIdx = battnumber; - frskyData.hub.minCellVolts = cellVolts; - } - } - break; - } - -#if defined(GPS) - case offsetof(FrskySerialData, hour): - frskyData.hub.hour = ((uint8_t)(frskyData.hub.hour + g_eeGeneral.timezone + 24)) % 24; - break; -#endif - - case offsetof(FrskySerialData, accelX): - case offsetof(FrskySerialData, accelY): - case offsetof(FrskySerialData, accelZ): - *(int16_t*)(&((uint8_t*)&frskyData.hub)[structPos]) /= 10; - break; - -#if 0 - case offsetof(FrskySerialData, gpsAltitude_bp): - case offsetof(FrskySerialData, fuelLevel): - case offsetof(FrskySerialData, gpsLongitude_bp): - case offsetof(FrskySerialData, gpsLatitude_bp): - case offsetof(FrskySerialData, gpsCourse_bp): - case offsetof(FrskySerialData, day): - case offsetof(FrskySerialData, year): - case offsetof(FrskySerialData, sec): - case offsetof(FrskySerialData, gpsSpeed_ap): - case offsetof(FrskySerialData, gpsLongitude_ap): - case offsetof(FrskySerialData, gpsLatitude_ap): - case offsetof(FrskySerialData, gpsCourse_ap): - case offsetof(FrskySerialData, gpsLongitudeEW): - case offsetof(FrskySerialData, gpsLatitudeNS): - case offsetof(FrskySerialData, varioSpeed): - case offsetof(FrskySerialData, power): /* because sent by openXsensor */ - case offsetof(FrskySerialData, vfas): - case offsetof(FrskySerialData, volts_bp): - break; - - default: - *((uint16_t *)(((uint8_t*)&frskyData.hub) + structPos)) = previousValue; - break; -#endif - } -} -#endif - -#if defined(WS_HOW_HIGH) -void parseTelemWSHowHighByte(uint8_t byte) -{ - if (frskyUsrStreaming < (FRSKY_TIMEOUT10ms*3 - 10)) { - ((uint8_t*)&frskyData.hub)[offsetof(FrskySerialData, baroAltitude_bp)] = byte; - checkMinMaxAltitude(); - if (g_model.frsky.varioSource == VARIO_SOURCE_ALTI) { - evalVario(frskyData.hub.baroAltitude_bp, 0); - } - } - else { - // At least 100mS passed since last data received - ((uint8_t*)&frskyData.hub)[offsetof(FrskySerialData, baroAltitude_bp)+1] = byte; - } - // baroAltitude_bp unit here is feet! - frskyUsrStreaming = FRSKY_TIMEOUT10ms*3; // reset counter -} -#endif - -void processFrskyPacket(uint8_t *packet) -{ - // What type of packet? - switch (packet[0]) - { - case LINKPKT: // A1/A2/RSSI values - { - link_counter += 32; - frskyData.analog[0].set(packet[1], g_model.frsky.channels[0].type); - frskyData.analog[1].set(packet[2], g_model.frsky.channels[1].type); - frskyData.rssi[0].set(packet[3]); - frskyData.rssi[1].set(packet[4] / 2); - frskyStreaming = FRSKY_TIMEOUT10ms; // reset counter only if valid frsky packets are being detected -#if defined(VARIO) - uint8_t varioSource = g_model.frsky.varioSource - VARIO_SOURCE_A1; - if (varioSource < 2) - frskyData.hub.varioSpeed = applyChannelRatio(varioSource, frskyData.analog[varioSource].value); -#endif - break; - } -#if defined(FRSKY_HUB) || defined (WS_HOW_HIGH) - case USRPKT: // User Data packet - uint8_t numBytes = 3 + (packet[1] & 0x07); // sanitize in case of data corruption leading to buffer overflow - for (uint8_t i=3; i>1) * (voltage>>1)) / 25; -#endif - - frskyData.hub.currentPrescale += current; - if (frskyData.hub.currentPrescale >= 3600) { - frskyData.hub.currentConsumption += 1; - frskyData.hub.currentPrescale -= 3600; - } - } - - if (frskyData.hub.power > frskyData.hub.maxPower) - frskyData.hub.maxPower = frskyData.hub.power; - } -} - -void telemetryWakeup() -{ -#if defined(PCBSKY9X) - rxPdcUsart(processSerialData); // Receive serial data here -#endif - - // Attempt to transmit any waiting Fr-Sky alarm set packets every 50ms (subject to packet buffer availability) - static uint8_t frskyTxDelay = 5; - if (frskyAlarmsSendState && (--frskyTxDelay == 0)) { - frskyTxDelay = 5; // 50ms - frskySendNextAlarm(); - } - -#ifndef SIMU -#if defined(WS_HOW_HIGH) - if (frskyUsrStreaming > 0) { - frskyUsrStreaming--; - } -#endif - - if (frskyStreaming > 0) { - frskyStreaming--; - } - else { - frskyData.rssi[0].set(0); - frskyData.rssi[1].set(0); - } -#endif - -#if defined(VARIO) - if (TELEMETRY_STREAMING() && !IS_FAI_ENABLED()) - varioWakeup(); -#endif -} - -#if 0 -// not used any more -bool FRSKY_alarmRaised(uint8_t idx) -{ - for (int i=0; i<2; i++) { - if (ALARM_LEVEL(idx, i) != alarm_off) { - if (ALARM_GREATER(idx, i)) { - if (frskyData.analog[idx].value > g_model.frsky.channels[idx].alarms_value[i]) - return true; - } - else { - if (frskyData.analog[idx].value < g_model.frsky.channels[idx].alarms_value[i]) - return true; - } - } - } - return false; -} -#endif - -#if !defined(CPUARM) -inline void FRSKY_EnableTXD(void) -{ - frskyTxBufferCount = 0; - UCSR0B |= (1 << TXEN0); // enable TX -} - -inline void FRSKY_EnableRXD(void) -{ - UCSR0B |= (1 << RXEN0); // enable RX - UCSR0B |= (1 << RXCIE0); // enable Interrupt -} -#endif - -void FRSKY_Init(void) -{ - // clear frsky variables - resetTelemetry(); - -#if defined(PCBTARANIS) - // TODO -#elif defined(PCBSKY9X) - startPdcUsartReceive() ; -#elif !defined(SIMU) - - DDRE &= ~(1 << DDE0); // set RXD0 pin as input - PORTE &= ~(1 << PORTE0); // disable pullup on RXD0 pin - -#undef BAUD -#define BAUD 9600 -#include - - UBRR0H = UBRRH_VALUE; - UBRR0L = UBRRL_VALUE; - UCSR0A &= ~(1 << U2X0); // disable double speed operation. - - // set 8N1 - UCSR0B = 0 | (0 << RXCIE0) | (0 << TXCIE0) | (0 << UDRIE0) | (0 << RXEN0) | (0 << TXEN0) | (0 << UCSZ02); - UCSR0C = 0 | (1 << UCSZ01) | (1 << UCSZ00); - - - while (UCSR0A & (1 << RXC0)) UDR0; // flush receive buffer - - // These should be running right from power up on a FrSky enabled '9X. - FRSKY_EnableTXD(); // enable FrSky-Telemetry reception - FRSKY_EnableRXD(); // enable FrSky-Telemetry reception -#endif -} - -void FrskyValueWithMin::set(uint8_t value) -{ - if (this->value == 0) { - this->value = value; - } - else { - sum += value; - if (link_counter == 0) { - this->value = sum / 8; - sum = 0; - } - } - - if (value && (!min || value < min)) - min = value; -} - -void FrskyValueWithMinMax::set(uint8_t value, uint8_t unit) -{ - FrskyValueWithMin::set(value); - if (unit != UNIT_VOLTS) { - this->value = value; - } - if (!max || value > max) - max = value; -} - -void resetTelemetry() -{ - memclear(&frskyData, sizeof(frskyData)); - -#if defined(FRSKY_HUB) - frskyData.hub.gpsLatitude_bp = 2; - frskyData.hub.gpsLongitude_bp = 2; - frskyData.hub.gpsFix = -1; -#endif - -#ifdef SIMU - frskyData.analog[0].set(120, UNIT_VOLTS); - frskyData.analog[1].set(240, UNIT_VOLTS); - frskyData.rssi[0].value = 75; - frskyData.rssi[1].value = 75; - frskyData.hub.fuelLevel = 75; - frskyData.hub.rpm = 12000; - -#if defined(GPS) - frskyData.hub.gpsFix = 1; - frskyData.hub.gpsLatitude_bp = 4401; - frskyData.hub.gpsLatitude_ap = 7710; - frskyData.hub.gpsLongitude_bp = 1006; - frskyData.hub.gpsLongitude_ap = 8872; - frskyData.hub.gpsSpeed_bp = (100 * 250) / 463; - getGpsPilotPosition(); - - frskyData.hub.gpsLatitude_bp = 4401; - frskyData.hub.gpsLatitude_ap = 7455; - frskyData.hub.gpsLongitude_bp = 1006; - frskyData.hub.gpsLongitude_ap = 9533; - getGpsDistance(); -#endif - - frskyData.hub.cellsCount = 6; - - frskyData.hub.gpsAltitude_bp = 50; - frskyData.hub.baroAltitude_bp = 50; - frskyData.hub.minAltitude = 10; - frskyData.hub.maxAltitude = 500; - - frskyData.hub.accelY = 100; - frskyData.hub.temperature1 = -30; - frskyData.hub.maxTemperature1 = 100; - - frskyData.hub.current = 5; - frskyData.hub.maxCurrent = 56; -#endif -} diff --git a/radio/src/telemetry/frsky_sport.cpp b/radio/src/telemetry/frsky_sport.cpp index 8499cb5f8..cf34b6198 100644 --- a/radio/src/telemetry/frsky_sport.cpp +++ b/radio/src/telemetry/frsky_sport.cpp @@ -179,11 +179,21 @@ void processHubPacket(uint8_t id, uint16_t value) } ((uint16_t*)&frskyData.hub)[id] = value; + float gear_ratio = 1; switch (id) { case RPM_ID: - frskyData.hub.rpm *= (uint8_t)60/(g_model.frsky.blades+2); + //frskyData.hub.rpm *= (uint8_t)60/(g_model.frsky.blades+2); + + // Change minimum Blades to 1 to allow for single sensors/raw data - T.Foley + // Added Spur and Pinion Ratio Calculation to provide final head/drive RPM after gearing + // + frskyData.hub.rpm *= (uint8_t)60; + frskyData.hub.rpm /= (g_model.frsky.blades+1); + gear_ratio = (((float)g_model.frsky.spur_gear+1) / ((float)g_model.frsky.pinion_gear+1)); + frskyData.hub.rpm = (float)(frskyData.hub.rpm / gear_ratio); + if (frskyData.hub.rpm > frskyData.hub.maxRpm) frskyData.hub.maxRpm = frskyData.hub.rpm; break;