/* * Copyright (C) EdgeTX * * Based on code named * opentx - https://github.com/opentx/opentx * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html * * 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 "edgetx.h" #include "hal/adc_driver.h" #include "hal/switch_driver.h" #include "hal/module_port.h" #include "hal/rgbleds.h" #include "analogs.h" #include "switches.h" #if defined(BLUETOOTH) #include "bluetooth_driver.h" #endif #if defined(CROSSFIRE) #include "telemetry/crossfire.h" #endif #if LCD_W >= 212 #define HW_SETTINGS_COLUMN1 12*FW #define HW_SETTINGS_COLUMN2 (20*FW - 3) #define HW_SETTINGS_COLUMN3 HW_SETTINGS_COLUMN2 #else #define HW_SETTINGS_COLUMN1 30 #define HW_SETTINGS_COLUMN2 (HW_SETTINGS_COLUMN1 + 5*FW) #define HW_SETTINGS_COLUMN3 HW_SETTINGS_COLUMN2 + FW #endif #if defined(BATTGRAPH) #define CASE_BATTGRAPH(x) x, #else #define CASE_BATTGRAPH(x) #endif enum { ITEM_RADIO_HARDWARE_LABEL_STICKS = 0, ITEM_RADIO_HARDWARE_STICK, ITEM_RADIO_HARDWARE_STICK_END = ITEM_RADIO_HARDWARE_STICK + MAX_STICKS - 1, ITEM_RADIO_HARDWARE_LABEL_POTS, ITEM_RADIO_HARDWARE_POT, ITEM_RADIO_HARDWARE_POT_END = ITEM_RADIO_HARDWARE_POT + MAX_POTS - 1, ITEM_RADIO_HARDWARE_LABEL_SWITCHES, ITEM_RADIO_HARDWARE_SWITCH, ITEM_RADIO_HARDWARE_SWITCH_END = ITEM_RADIO_HARDWARE_SWITCH + MAX_SWITCHES - 1, #if defined(FUNCTION_SWITCHES) ITEM_RADIO_HARDWARE_LABEL_CFS, ITEM_RADIO_HARDWARE_CFS, ITEM_RADIO_HARDWARE_CFS_END = ITEM_RADIO_HARDWARE_CFS + MAX_SWITCHES - 1, #endif CASE_BATTGRAPH(ITEM_RADIO_HARDWARE_BATT_RANGE) ITEM_RADIO_HARDWARE_BATTERY_CALIB, ITEM_RADIO_HARDWARE_RTC_BATTERY, ITEM_RADIO_HARDWARE_RTC_CHECK, #if defined(AUDIO_MUTE_GPIO) ITEM_RADIO_HARDWARE_AUDIO_MUTE, #endif ITEM_RADIO_HARDWARE_LABEL_INTERNAL_MODULE, ITEM_RADIO_HARDWARE_INTERNAL_MODULE_TYPE, ITEM_RADIO_HARDWARE_INTERNAL_MODULE_BAUDRATE, ITEM_RADIO_HARDWARE_SERIAL_SAMPLE_MODE, #if defined(BLUETOOTH) ITEM_RADIO_HARDWARE_BLUETOOTH_MODE, ITEM_RADIO_HARDWARE_BLUETOOTH_PAIRING_CODE, ITEM_RADIO_HARDWARE_BLUETOOTH_LOCAL_ADDR, ITEM_RADIO_HARDWARE_BLUETOOTH_DISTANT_ADDR, ITEM_RADIO_HARDWARE_BLUETOOTH_NAME, #endif #if defined(EXTERNAL_ANTENNA) ITEM_RADIO_HARDWARE_EXTERNAL_ANTENNA, #endif ITEM_RADIO_HARDWARE_SERIAL_PORT_LABEL, ITEM_RADIO_HARDWARE_SERIAL_PORT, ITEM_RADIO_HARDWARE_SERIAL_PORT_END = ITEM_RADIO_HARDWARE_SERIAL_PORT + MAX_SERIAL_PORTS - 1, ITEM_RADIO_HARDWARE_JITTER_FILTER, ITEM_RADIO_HARDWARE_RAS, ITEM_RADIO_HARDWARE_SPORT_UPDATE_POWER, #if (defined(BACKLIGHT_GPIO) || OLED_SCREEN) && (LCD_W == 128) ITEM_RADIO_HARDWARE_SCREEN_LABEL, ITEM_RADIO_HARDWARE_SCREEN_INVERT, #endif ITEM_RADIO_HARDWARE_DEBUG, #if defined(FUNCTION_SWITCHES) ITEM_RADIO_HARDWARE_DEBUG_FS, #endif ITEM_RADIO_HARDWARE_MAX }; #if defined(EXTERNAL_ANTENNA) static void onHardwareAntennaSwitchConfirm(const char * result) { if (result == STR_OK) { // Switch to external antenna confirmation g_eeGeneral.antennaMode = reusableBuffer.radioHardware.antennaMode; storageDirty(EE_GENERAL); // Consent already obtained above; mark enabled so checkExternalAntenna() // applies the GPIO instead of asking again. globalData.externalAntennaEnabled = true; checkExternalAntenna(); } else { reusableBuffer.radioHardware.antennaMode = g_eeGeneral.antennaMode; } } #endif // defined(EXTERNAL_ANTENNA) #if defined(FUNCTION_SWITCHES) #define RADIO_SETUP_2ND_COLUMN (LCD_W-11*FW) extern const char* _fct_sw_start[]; extern int swIndex; extern bool checkCFSTypeAvailable(int val); enum CFSFields { CFS_FIELD_TYPE, CFS_FIELD_NAME, CFS_FIELD_START, #if defined(FUNCTION_SWITCHES_RGB_LEDS) CFS_FIELD_COLOR_LABEL, CFS_FIELD_ON_COLOR, CFS_FIELD_ON_LUA_OVERRIDE, CFS_FIELD_OFF_COLOR, CFS_FIELD_OFF_LUA_OVERRIDE, #endif CFS_FIELD_COUNT }; #if defined(FUNCTION_SWITCHES_RGB_LEDS) extern bool menuCFSpreview; extern void menuCFSColor(coord_t y, RGBLedColor& color, const char* title, LcdFlags attr, event_t event); #endif static void menuRadioCFSOne(event_t event) { std::string s(CHAR_SWITCH); s += switchGetDefaultName(swIndex); int config = g_eeGeneral.switchType(swIndex); uint8_t group = g_eeGeneral.switchGroup(swIndex); int startPos = g_eeGeneral.switchStart(swIndex); SUBMENU(s.c_str(), CFS_FIELD_COUNT, { 0, (uint8_t)((config != SWITCH_NONE && config != SWITCH_GLOBAL) ? 0 : HIDDEN_ROW), (uint8_t)((config != SWITCH_NONE && config != SWITCH_TOGGLE && config != SWITCH_GLOBAL && group == 0) ? 0 : HIDDEN_ROW), #if defined(FUNCTION_SWITCHES_RGB_LEDS) (uint8_t)((config != SWITCH_NONE && config != SWITCH_GLOBAL) ? LABEL() : HIDDEN_ROW), (uint8_t)((config != SWITCH_NONE && config != SWITCH_GLOBAL) ? 3 : HIDDEN_ROW), (uint8_t)((config != SWITCH_NONE && config != SWITCH_GLOBAL) ? 0 : HIDDEN_ROW), (uint8_t)((config != SWITCH_NONE && config != SWITCH_GLOBAL) ? 3 : HIDDEN_ROW), (uint8_t)((config != SWITCH_NONE && config != SWITCH_GLOBAL) ? 0 : HIDDEN_ROW), #endif }); int8_t sub = menuVerticalPosition; int8_t editMode = s_editMode; coord_t y = MENU_HEADER_HEIGHT + 1; #if defined(FUNCTION_SWITCHES_RGB_LEDS) menuCFSpreview = false; #endif for (int k = 0; k < NUM_BODY_LINES; k += 1) { int i = k + menuVerticalOffset; for (int j = 0; j <= i; j += 1) { if (j < (int)DIM(mstate_tab) && mstate_tab[j] == HIDDEN_ROW) { i += 1; } } LcdFlags attr = (sub == i ? (editMode > 0 ? BLINK | INVERS : INVERS) : 0); switch(i) { case CFS_FIELD_TYPE: config = editChoice(RADIO_SETUP_2ND_COLUMN, y, STR_SWITCH_TYPE, STR_SWTYPES, config, SWITCH_NONE, SWITCH_3POS, attr, event, 0, checkCFSTypeAvailable); if (attr && checkIncDec_Ret) { g_eeGeneral.switchSetType(swIndex, (SwitchConfig)config); if (config == SWITCH_NONE) { #if defined(FUNCTION_SWITCHES_RGB_LEDS) if (g_model.getSwitchType(swIndex) == SWITCH_NONE) fsLedRGB(switchGetCustomSwitchIdx(swIndex), 0); #endif } else if (config == SWITCH_TOGGLE) { setFSLogicalState(swIndex, 0); g_eeGeneral.switchSetStart(swIndex, FS_START_PREVIOUS); // Toggle switches do not have startup position } } break; case CFS_FIELD_NAME: editSingleName(RADIO_SETUP_2ND_COLUMN, y, STR_NAME, g_eeGeneral.switchName(swIndex), LEN_SWITCH_NAME, event, (attr != 0), editMode); break; case CFS_FIELD_START: lcdDrawText(0, y, STR_SWITCH_STARTUP); lcdDrawText(RADIO_SETUP_2ND_COLUMN, y, _fct_sw_start[startPos], attr ? (s_editMode ? INVERS + BLINK : INVERS) : 0); if (attr) { startPos = checkIncDec(event, startPos, FS_START_OFF, FS_START_PREVIOUS, EE_MODEL); g_eeGeneral.switchSetStart(swIndex, (fsStartPositionType)startPos); } break; #if defined(FUNCTION_SWITCHES_RGB_LEDS) case CFS_FIELD_COLOR_LABEL: lcdDrawText(0, y, STR_BLCOLOR); lcdDrawText(LCD_W - 6 * FW, y, "R", RIGHT | SMLSIZE); lcdDrawText(LCD_W - 3 * FW, y, "G", RIGHT | SMLSIZE); lcdDrawText(LCD_W, y, "B", RIGHT | SMLSIZE); break; case CFS_FIELD_ON_COLOR: menuCFSColor(y, g_eeGeneral.switchOnColor(swIndex), STR_OFFON[1], attr, event); break; case CFS_FIELD_ON_LUA_OVERRIDE: g_eeGeneral.cfsSetOnColorLuaOverride(swIndex, editCheckBox(g_eeGeneral.cfsOnColorLuaOverride(swIndex), LCD_W - 2 * FW, y, STR_LUA_OVERRIDE, attr, event, INDENT_WIDTH)); break; case CFS_FIELD_OFF_COLOR: menuCFSColor(y, g_eeGeneral.switchOffColor(swIndex), STR_OFFON[0], attr, event); break; case CFS_FIELD_OFF_LUA_OVERRIDE: g_eeGeneral.cfsSetOffColorLuaOverride(swIndex, editCheckBox(g_eeGeneral.cfsOffColorLuaOverride(swIndex), LCD_W - 2 * FW, y, STR_LUA_OVERRIDE, attr, event, INDENT_WIDTH)); break; #endif } y += FH; } #if defined(FUNCTION_SWITCHES_RGB_LEDS) if (!menuCFSpreview) setFSEditOverride(-1, 0); #endif } #endif static uint8_t _dispSerialPort(uint8_t port_nr) { auto port = serialGetPort(port_nr); if (!port || !port->name) return HIDDEN_ROW; return 0; } static bool _isAux1ModeAvailable(int m) { return isSerialModeAvailable(SP_AUX1, m); } static bool _isAux2ModeAvailable(int m) { return isSerialModeAvailable(SP_AUX2, m); } static bool _isVCPModeAvailable(int m) { return isSerialModeAvailable(SP_VCP, m); } static const IsValueAvailable _isSerialModeAvailable[MAX_SERIAL_PORTS] = { _isAux1ModeAvailable, _isAux2ModeAvailable, _isVCPModeAvailable }; static void _init_menu_tab_array(uint8_t* tab, size_t len) { memset((void*)tab, READONLY_ROW, sizeof(MENU_TAB_ARRAY_TYPE) * len); tab += HEADER_LINE; // skip header line tab[ITEM_RADIO_HARDWARE_LABEL_STICKS] = 0; // calib button auto max_sticks = adcGetMaxInputs(ADC_INPUT_MAIN); for (int i = ITEM_RADIO_HARDWARE_STICK; i <= ITEM_RADIO_HARDWARE_STICK_END; i++) { uint8_t idx = i - ITEM_RADIO_HARDWARE_STICK; tab[i] = idx < max_sticks ? 1 : HIDDEN_ROW; } auto max_pots = adcGetMaxInputs(ADC_INPUT_FLEX); for (int i = ITEM_RADIO_HARDWARE_POT; i <= ITEM_RADIO_HARDWARE_POT_END; i++) { uint8_t idx = i - ITEM_RADIO_HARDWARE_POT; tab[i] = idx < max_pots ? (IS_POT_MULTIPOS(idx) ? 1 : 2) : HIDDEN_ROW; } int max_switches = switchGetMaxAllSwitches(); for (int i = ITEM_RADIO_HARDWARE_SWITCH; i <= ITEM_RADIO_HARDWARE_SWITCH_END; i++) { uint8_t idx = i - ITEM_RADIO_HARDWARE_SWITCH; if (idx < max_switches && !switchIsCustomSwitch(idx)) { tab[i] = switchIsFlex(idx) ? 2 : 1; } else { tab[i] = HIDDEN_ROW; } } #if defined (FUNCTION_SWITCHES) for (int i = ITEM_RADIO_HARDWARE_CFS; i <= ITEM_RADIO_HARDWARE_CFS_END; i++) { uint8_t idx = i - ITEM_RADIO_HARDWARE_CFS; if (idx < max_switches && switchIsCustomSwitch(idx)) { tab[i] = 0; } else { tab[i] = HIDDEN_ROW; } } #endif #if defined(BATTGRAPH) tab[ITEM_RADIO_HARDWARE_BATT_RANGE] = 1; #endif tab[ITEM_RADIO_HARDWARE_BATTERY_CALIB] = 0; tab[ITEM_RADIO_HARDWARE_RTC_BATTERY] = READONLY_ROW; tab[ITEM_RADIO_HARDWARE_RTC_CHECK] = 0; #if defined(AUDIO_MUTE_GPIO) tab[ITEM_RADIO_HARDWARE_AUDIO_MUTE] = 0; #endif #if defined(HARDWARE_INTERNAL_MODULE) tab[ITEM_RADIO_HARDWARE_INTERNAL_MODULE_TYPE] = 0; tab[ITEM_RADIO_HARDWARE_INTERNAL_MODULE_BAUDRATE] = isInternalModuleCrossfire() ? (uint8_t)0 : HIDDEN_ROW; #else memset((void*)&tab[ITEM_RADIO_HARDWARE_LABEL_INTERNAL_MODULE], HIDDEN_ROW, 3); #endif #if defined(HARDWARE_EXTERNAL_MODULE) && (defined(STM32F2) || defined(STM32F4)) tab[ITEM_RADIO_HARDWARE_SERIAL_SAMPLE_MODE] = 0; #else tab[ITEM_RADIO_HARDWARE_SERIAL_SAMPLE_MODE] = HIDDEN_ROW; #endif #if defined(BLUETOOTH) bool has_bt = IS_BLUETOOTH_CHIP_PRESENT(); tab[ITEM_RADIO_HARDWARE_BLUETOOTH_MODE] = has_bt ? 0 : HIDDEN_ROW; bool bt_telem = g_eeGeneral.bluetoothMode == BLUETOOTH_TELEMETRY; tab[ITEM_RADIO_HARDWARE_BLUETOOTH_PAIRING_CODE] = bt_telem ? READONLY_ROW : HIDDEN_ROW; bool bt_off = g_eeGeneral.bluetoothMode == BLUETOOTH_OFF; tab[ITEM_RADIO_HARDWARE_BLUETOOTH_LOCAL_ADDR] = bt_off ? HIDDEN_ROW : READONLY_ROW; tab[ITEM_RADIO_HARDWARE_BLUETOOTH_DISTANT_ADDR] = bt_off ? HIDDEN_ROW : READONLY_ROW; tab[ITEM_RADIO_HARDWARE_BLUETOOTH_NAME] = bt_off ? HIDDEN_ROW : 0; #endif #if defined(EXTERNAL_ANTENNA) tab[ITEM_RADIO_HARDWARE_EXTERNAL_ANTENNA] = #if defined(INTMODULE_ANTSEL_GPIO) 0; #else g_eeGeneral.internalModule == MODULE_TYPE_XJT_PXX1 ? 0 : HIDDEN_ROW; #endif #endif bool has_serial = false; for (int i = 0; i < MAX_SERIAL_PORTS; i++) { uint8_t idx = ITEM_RADIO_HARDWARE_SERIAL_PORT + i; auto r = _dispSerialPort(i); tab[idx] = r; has_serial = has_serial || (!r); } tab[ITEM_RADIO_HARDWARE_SERIAL_PORT_LABEL] = has_serial ? READONLY_ROW : HIDDEN_ROW; tab[ITEM_RADIO_HARDWARE_JITTER_FILTER] = 0; tab[ITEM_RADIO_HARDWARE_RAS] = READONLY_ROW; auto mod_desc = modulePortGetModuleDescription(SPORT_MODULE); if (mod_desc && mod_desc->set_pwr) { tab[ITEM_RADIO_HARDWARE_SPORT_UPDATE_POWER] = 0; } else { tab[ITEM_RADIO_HARDWARE_SPORT_UPDATE_POWER] = HIDDEN_ROW; } #if (defined(BACKLIGHT_GPIO) || OLED_SCREEN) && (LCD_W == 128) tab[ITEM_RADIO_HARDWARE_SCREEN_LABEL] = READONLY_ROW; tab[ITEM_RADIO_HARDWARE_SCREEN_INVERT] = 0; #endif tab[ITEM_RADIO_HARDWARE_DEBUG] = 1; #if defined(FUNCTION_SWITCHES) tab[ITEM_RADIO_HARDWARE_DEBUG_FS] = 0; #endif } static bool editInversion(bool state, event_t event, coord_t y, LcdFlags flags) { lcdDrawChar(LCD_W - 8, y, state ? 127 : 126, flags); if (flags & (~RIGHT)) state = checkIncDec(event, state, 0, 1, EE_GENERAL); return state; } void menuRadioHardware(event_t event) { uint8_t old_editMode = s_editMode; uint8_t MENU_TAB_ARRAY_NAME[HEADER_LINE + ITEM_RADIO_HARDWARE_MAX]; _init_menu_tab_array(MENU_TAB_ARRAY_NAME, HEADER_LINE + ITEM_RADIO_HARDWARE_MAX); MENU_CHECK(menuTabGeneral, MENU_RADIO_HARDWARE, HEADER_LINE + ITEM_RADIO_HARDWARE_MAX); title(STR_HARDWARE); uint8_t sub = menuVerticalPosition - HEADER_LINE; #if defined(BLUETOOTH) if (g_eeGeneral.bluetoothMode != BLUETOOTH_OFF && !IS_BLUETOOTH_CHIP_PRESENT()) { g_eeGeneral.bluetoothMode = BLUETOOTH_OFF; storageDirty(EE_GENERAL); } #endif if (menuEvent) { disableVBatBridge(); } else if (event == EVT_ENTRY) { enableVBatBridge(); #if defined(EXTERNAL_ANTENNA) reusableBuffer.radioHardware.antennaMode = g_eeGeneral.antennaMode; #endif } for (uint8_t i=0; i0) ? BLINK|INVERS : INVERS); LcdFlags attr = (sub == k ? blink : 0); switch(k) { case ITEM_RADIO_HARDWARE_LABEL_STICKS: lcdDrawTextAlignedLeft(y, STR_STICKS); lcdDrawText(HW_SETTINGS_COLUMN2, y, STR_CALIBRATION, attr); if (attr && event == EVT_KEY_BREAK(KEY_ENTER)) { pushMenu(menuRadioCalibration); } break; case ITEM_RADIO_HARDWARE_LABEL_POTS: lcdDrawTextAlignedLeft(y, STR_POTS); break; case ITEM_RADIO_HARDWARE_LABEL_SWITCHES: lcdDrawTextAlignedLeft(y, STR_SWITCHES); break; #if defined(FUNCTION_SWITCHES) case ITEM_RADIO_HARDWARE_LABEL_CFS: lcdDrawTextAlignedLeft(y, STR_FUNCTION_SWITCHES); break; #endif #if defined(BATTGRAPH) case ITEM_RADIO_HARDWARE_BATT_RANGE: lcdDrawTextAlignedLeft(y, STR_BATTERY_RANGE); putsVolts(HW_SETTINGS_COLUMN3, y, 90+g_eeGeneral.vBatMin, (menuHorizontalPosition==0 ? attr : 0)|NO_UNIT); lcdDrawChar(lcdNextPos, y, '-'); putsVolts(lcdNextPos, y, 120+g_eeGeneral.vBatMax, (menuHorizontalPosition>0 ? attr : 0)|NO_UNIT); if (attr && s_editMode>0) { if (menuHorizontalPosition==0) CHECK_INCDEC_GENVAR(event, g_eeGeneral.vBatMin, -60, g_eeGeneral.vBatMax+29); // min=3.0V else CHECK_INCDEC_GENVAR(event, g_eeGeneral.vBatMax, g_eeGeneral.vBatMin-29, +40); // max=16.0V } break; #endif case ITEM_RADIO_HARDWARE_BATTERY_CALIB: lcdDrawTextAlignedLeft(y, STR_BATT_CALIB); putsVolts(HW_SETTINGS_COLUMN3, y, getBatteryVoltage(), attr|PREC2|LEFT); if (attr) { CHECK_INCDEC_GENVAR(event, g_eeGeneral.txVoltageCalibration, -127, 127); } break; case ITEM_RADIO_HARDWARE_RTC_BATTERY: lcdDrawTextAlignedLeft(y, STR_RTC_BATT); putsVolts(HW_SETTINGS_COLUMN3, y, getRTCBatteryVoltage(), PREC2|LEFT); break; case ITEM_RADIO_HARDWARE_RTC_CHECK: g_eeGeneral.disableRtcWarning = 1 - editCheckBox(1 - g_eeGeneral.disableRtcWarning, HW_SETTINGS_COLUMN2, y, STR_RTC_CHECK, attr, event); break; case ITEM_RADIO_HARDWARE_LABEL_INTERNAL_MODULE: lcdDrawTextAlignedLeft(y, STR_INTERNALRF); break; case ITEM_RADIO_HARDWARE_INTERNAL_MODULE_TYPE: { g_eeGeneral.internalModule = editChoice(HW_SETTINGS_COLUMN2, y, STR_TYPE, STR_MODULE_PROTOCOLS, g_eeGeneral.internalModule, MODULE_TYPE_NONE, MODULE_TYPE_MAX, attr, event, INDENT_WIDTH, isInternalModuleSupported); if (g_model.moduleData[INTERNAL_MODULE].type != g_eeGeneral.internalModule) { memclear(&g_model.moduleData[INTERNAL_MODULE], sizeof(ModuleData)); storageDirty(EE_MODEL); storageDirty(EE_GENERAL); #if defined(CROSSFIRE) && defined(USB_SERIAL) // If USB-VCP was off, set it to CLI to enable passthrough flashing if (isInternalModuleCrossfire() && serialGetMode(SP_VCP) == UART_MODE_NONE) serialSetMode(SP_VCP, UART_MODE_CLI); #endif } } break; #if defined(AUDIO_MUTE_GPIO) case ITEM_RADIO_HARDWARE_AUDIO_MUTE: g_eeGeneral.audioMuteEnable = editCheckBox(g_eeGeneral.audioMuteEnable, HW_SETTINGS_COLUMN2, y, STR_AUDIO_MUTE, attr, event); break; #endif case ITEM_RADIO_HARDWARE_INTERNAL_MODULE_BAUDRATE: lcdDrawTextIndented(y, STR_BAUDRATE); lcdDrawTextAtIndex(HW_SETTINGS_COLUMN2, y, STR_CRSF_BAUDRATE, CROSSFIRE_STORE_TO_INDEX(g_eeGeneral.internalModuleBaudrate),attr | LEFT); if (attr) { g_eeGeneral.internalModuleBaudrate = CROSSFIRE_INDEX_TO_STORE(checkIncDecModel(event, CROSSFIRE_STORE_TO_INDEX(g_eeGeneral.internalModuleBaudrate), 0, CROSSFIRE_MAX_INTERNAL_BAUDRATE)); if (checkIncDec_Ret) { restartModule(INTERNAL_MODULE); } } break; #if defined(STM32F2) || defined(STM32F4) case ITEM_RADIO_HARDWARE_SERIAL_SAMPLE_MODE: g_eeGeneral.uartSampleMode = editChoice(HW_SETTINGS_COLUMN2, y, STR_SAMPLE_MODE, STR_SAMPLE_MODES, g_eeGeneral.uartSampleMode, 0, UART_SAMPLE_MODE_MAX, attr, event); if (attr && checkIncDec_Ret) { restartModule(EXTERNAL_MODULE); } break; #endif #if defined(BLUETOOTH) case ITEM_RADIO_HARDWARE_BLUETOOTH_MODE: lcdDrawTextAlignedLeft(y, STR_BLUETOOTH); lcdDrawTextAtIndex(HW_SETTINGS_COLUMN2, y, STR_BLUETOOTH_MODES, g_eeGeneral.bluetoothMode, attr); if (attr) { g_eeGeneral.bluetoothMode = checkIncDecGen(event, g_eeGeneral.bluetoothMode, BLUETOOTH_OFF, BLUETOOTH_MAX); } break; case ITEM_RADIO_HARDWARE_BLUETOOTH_PAIRING_CODE: lcdDrawTextIndented(y, STR_BLUETOOTH_PIN_CODE); lcdDrawText(HW_SETTINGS_COLUMN2, y, "000000"); break; case ITEM_RADIO_HARDWARE_BLUETOOTH_LOCAL_ADDR: lcdDrawTextIndented(y, STR_BLUETOOTH_LOCAL_ADDR); lcdDrawText(HW_SETTINGS_COLUMN2, y, bluetooth.localAddr[0] == '\0' ? "---" : bluetooth.localAddr); break; case ITEM_RADIO_HARDWARE_BLUETOOTH_DISTANT_ADDR: lcdDrawTextIndented(y, STR_BLUETOOTH_DIST_ADDR); lcdDrawText(HW_SETTINGS_COLUMN2, y, bluetooth.distantAddr[0] == '\0' ? "---" : bluetooth.distantAddr); break; case ITEM_RADIO_HARDWARE_BLUETOOTH_NAME: lcdDrawTextIndented(y, STR_NAME); editName(HW_SETTINGS_COLUMN2, y, g_eeGeneral.bluetoothName, LEN_BLUETOOTH_NAME, event, (attr != 0), attr, old_editMode); break; #endif #if defined(EXTERNAL_ANTENNA) case ITEM_RADIO_HARDWARE_EXTERNAL_ANTENNA: reusableBuffer.radioHardware.antennaMode = editChoice(HW_SETTINGS_COLUMN2, y, STR_ANTENNA, STR_ANTENNA_MODES, reusableBuffer.radioHardware.antennaMode, ANTENNA_MODE_INTERNAL, ANTENNA_MODE_EXTERNAL, attr, event); if (!s_editMode && reusableBuffer.radioHardware.antennaMode != g_eeGeneral.antennaMode) { if (!isExternalAntennaEnabled() && (reusableBuffer.radioHardware.antennaMode == ANTENNA_MODE_EXTERNAL || (reusableBuffer.radioHardware.antennaMode == ANTENNA_MODE_PER_MODEL && g_model.moduleData[INTERNAL_MODULE].antennaMode == ANTENNA_MODE_EXTERNAL))) { POPUP_CONFIRMATION(STR_ANTENNACONFIRM1, onHardwareAntennaSwitchConfirm); SET_WARNING_INFO(STR_ANTENNACONFIRM2, strlen(STR_ANTENNACONFIRM2), 0); } else { g_eeGeneral.antennaMode = reusableBuffer.radioHardware.antennaMode; checkExternalAntenna(); } } break; #endif case ITEM_RADIO_HARDWARE_SERIAL_PORT_LABEL: lcdDrawTextAlignedLeft(y, STR_AUX_SERIAL_MODE); break; case ITEM_RADIO_HARDWARE_JITTER_FILTER: g_eeGeneral.noJitterFilter = 1 - editCheckBox(1 - g_eeGeneral.noJitterFilter, HW_SETTINGS_COLUMN2, y, STR_JITTER_FILTER, attr, event); break; case ITEM_RADIO_HARDWARE_RAS: #if defined(HARDWARE_INTERNAL_RAS) lcdDrawTextAlignedLeft(y, "RAS"); if (telemetryData.swrInternal.isFresh()) lcdDrawNumber(HW_SETTINGS_COLUMN2, y, telemetryData.swrInternal.value()); else lcdDrawText(HW_SETTINGS_COLUMN2, y, "---"); lcdDrawText(lcdNextPos, y, "/"); #else lcdDrawTextAlignedLeft(y, "Ext. RAS"); lcdNextPos = HW_SETTINGS_COLUMN2; #endif if (telemetryData.swrExternal.isFresh()) lcdDrawNumber(lcdNextPos, y, telemetryData.swrExternal.value()); else lcdDrawText(lcdNextPos, y, "---"); break; case ITEM_RADIO_HARDWARE_SPORT_UPDATE_POWER: g_eeGeneral.sportUpdatePower = editChoice(HW_SETTINGS_COLUMN2, y, STR_SPORT_UPDATE_POWER_MODE, STR_SPORT_UPDATE_POWER_MODES, g_eeGeneral.sportUpdatePower, 0, 1, attr, event); if (attr && checkIncDec_Ret) { modulePortSetPower(SPORT_MODULE, g_eeGeneral.sportUpdatePower); } break; #if (defined(BACKLIGHT_GPIO) || OLED_SCREEN) && (LCD_W == 128) case ITEM_RADIO_HARDWARE_SCREEN_LABEL: lcdDrawTextAlignedLeft(y, STR_SCREEN); break; case ITEM_RADIO_HARDWARE_SCREEN_INVERT: { lcdDrawText(INDENT_WIDTH, y, STR_MENU_INVERT); bool inv = g_eeGeneral.invertLCD; g_eeGeneral.invertLCD = editCheckBox(g_eeGeneral.invertLCD, HW_SETTINGS_COLUMN2, y, nullptr, attr, event); if (inv != g_eeGeneral.invertLCD) lcdSetInvert(g_eeGeneral.invertLCD); } break; #endif case ITEM_RADIO_HARDWARE_DEBUG: lcdDrawTextAlignedLeft(y, STR_DEBUG); lcdDrawText(HW_SETTINGS_COLUMN2, y, STR_ANALOGS_BTN, menuHorizontalPosition == 0 ? attr : 0); lcdDrawText(lcdLastRightPos + 2, y, STR_KEYS_BTN, menuHorizontalPosition == 1 ? attr : 0); if (attr && event == EVT_KEY_BREAK(KEY_ENTER)) { if (menuHorizontalPosition == 0) pushMenu(menuRadioDiagAnalogs); else pushMenu(menuRadioDiagKeys); } break; #if defined(FUNCTION_SWITCHES) case ITEM_RADIO_HARDWARE_DEBUG_FS: lcdDrawText(HW_SETTINGS_COLUMN2, y, STR_FS_BTN, attr); if (attr && event == EVT_KEY_BREAK(KEY_ENTER)) { pushMenu(menuRadioDiagFS); } break; #endif default: if (k <= ITEM_RADIO_HARDWARE_STICK_END) { // Sticks int idx = k - ITEM_RADIO_HARDWARE_STICK; editStickHardwareSettings(HW_SETTINGS_COLUMN1, y, idx, event, menuHorizontalPosition == 0 ? attr : 0, old_editMode); // ADC inversion setStickInversion(idx, editInversion(getStickInversion(idx), event, y, menuHorizontalPosition == 1 ? attr : 0)); } else if (k <= ITEM_RADIO_HARDWARE_POT_END) { // Pots & sliders int idx = k - ITEM_RADIO_HARDWARE_POT; // draw hw name LcdFlags flags = menuHorizontalPosition < 0 ? attr : 0; lcdDrawText(INDENT_WIDTH, y, CHAR_POT, flags); lcdDrawText(lcdNextPos, y, adcGetInputLabel(ADC_INPUT_FLEX, idx), flags); // draw custom name if (analogHasCustomLabel(ADC_INPUT_FLEX, idx) || (attr && s_editMode > 0 && menuHorizontalPosition == 0)) { editName(HW_SETTINGS_COLUMN1, y, (char*)analogGetCustomLabel(ADC_INPUT_FLEX, idx), LEN_ANA_NAME, event, attr && menuHorizontalPosition == 0, 0, old_editMode); } else { lcdDrawMMM(HW_SETTINGS_COLUMN1, y, menuHorizontalPosition==0 ? attr : 0); } // pot config uint8_t potType = getPotType(idx); potType = editChoice(HW_SETTINGS_COLUMN2, y, "", STR_POTTYPES, potType, FLEX_NONE, FLEX_SWITCH, menuHorizontalPosition == 1 ? attr : 0, event); if (checkIncDec_Ret) switchFixFlexConfig(); setPotType(idx, potType); if (!IS_POT_MULTIPOS(idx)) { // ADC inversion setPotInversion(idx, editInversion(getPotInversion(idx), event, y, menuHorizontalPosition == 2 ? attr : 0)); } else if (getPotInversion(idx)) { setPotInversion(idx, 0); storageDirty(EE_GENERAL); } } else if (k <= ITEM_RADIO_HARDWARE_SWITCH_END) { // Switches int index = k - ITEM_RADIO_HARDWARE_SWITCH; int config = g_eeGeneral.switchType(index); LcdFlags flags = menuHorizontalPosition < 0 ? attr : 0; lcdDrawText(INDENT_WIDTH, y, CHAR_SWITCH, flags); lcdDrawText(lcdNextPos, y, switchGetDefaultName(index), flags); if (switchIsFlex(index)) { // flexSwitch source flags = menuHorizontalPosition == 0 ? attr : 0; auto source = switchGetFlexConfig(index); lcdDrawText(HW_SETTINGS_COLUMN1, y, (source < 0) ? STR_NONE : adcGetInputLabel(ADC_INPUT_FLEX, source), flags); if (flags & (~RIGHT)) source = checkIncDec(event, source, -1, adcGetMaxInputs(ADC_INPUT_FLEX) - 1, EE_GENERAL, isFlexSwitchSourceValid); switchConfigFlex(index, source); //Name flags = menuHorizontalPosition == 1 ? attr : 0; if (g_eeGeneral.switchHasCustomName(index) || (attr && s_editMode > 0 && menuHorizontalPosition == 1)) { editName(HW_SETTINGS_COLUMN2, y, g_eeGeneral.getSwitchCustomName(index), LEN_SWITCH_NAME, event, flags, 0, old_editMode); } else { lcdDrawMMM(HW_SETTINGS_COLUMN2, y, flags); } // Switch type flags = menuHorizontalPosition == 2 ? attr : 0; config = editChoice(HW_SETTINGS_COLUMN2 + 25, y, "", STR_SWTYPES, config, SWITCH_NONE, switchGetMaxType(index), flags, event); if (attr && checkIncDec_Ret) { g_eeGeneral.switchSetType(index, (SwitchConfig)config); } } else { flags = menuHorizontalPosition == 0 ? attr : 0; if (g_eeGeneral.switchHasCustomName(index) || (attr && s_editMode > 0 && menuHorizontalPosition == 0)) { editName(HW_SETTINGS_COLUMN1, y, g_eeGeneral.getSwitchCustomName(index), LEN_SWITCH_NAME, event, flags, 0, old_editMode); } else { lcdDrawMMM(HW_SETTINGS_COLUMN1, y, flags); } flags = menuHorizontalPosition == 1 ? attr : 0; config = editChoice(HW_SETTINGS_COLUMN2, y, "", STR_SWTYPES, config, SWITCH_NONE, switchGetMaxType(index), flags, event); if (attr && checkIncDec_Ret) { g_eeGeneral.switchSetType(index, (SwitchConfig)config); } } #if defined(FUNCTION_SWITCHES) } else if (k <= ITEM_RADIO_HARDWARE_CFS_END) { // Customisable Switches int index = k - ITEM_RADIO_HARDWARE_CFS; int config = g_eeGeneral.switchType(index); lcdDrawText(INDENT_WIDTH, y, CHAR_SWITCH, attr); lcdDrawText(lcdNextPos, y, switchGetDefaultName(index), attr); lcdDrawText(HW_SETTINGS_COLUMN2, y, STR_SWTYPES[config]); if (attr && event == EVT_KEY_BREAK(KEY_ENTER)) { swIndex = index; pushMenu(menuRadioCFSOne); } if (config != SWITCH_NONE) { if (g_eeGeneral.switchName(index)[0]) { char s[LEN_SWITCH_NAME + 1]; strAppend(s, g_eeGeneral.switchName(index), LEN_SWITCH_NAME); lcdDrawText(HW_SETTINGS_COLUMN1, y, s); } else { lcdDrawMMM(HW_SETTINGS_COLUMN1, y, 0); } uint8_t group = g_eeGeneral.switchGroup(index); // lcdDrawText(30 + 13 * FW, y, STR_FSGROUPS[group]); if (config != SWITCH_TOGGLE && group == 0) { int startPos = g_eeGeneral.switchStart(index); lcdDrawText(30 + 15 * FW, y, _fct_sw_start[startPos]); } } #endif } else if (k <= ITEM_RADIO_HARDWARE_SERIAL_PORT_END) { auto port_nr = k - ITEM_RADIO_HARDWARE_SERIAL_PORT; auto port = serialGetPort(port_nr); if (port && port->name) { lcdDrawTextIndented(y, port->name); auto mode = serialGetMode(port_nr); mode = editChoice(HW_SETTINGS_COLUMN2, y, nullptr, STR_AUX_SERIAL_MODES, mode, 0, UART_MODE_MAX, attr, event, 0, _isSerialModeAvailable[port_nr]); if (attr && checkIncDec_Ret) { serialSetMode(port_nr, mode); serialInit(port_nr, mode); } } } break; } } }