diff --git a/radio/src/datastructs.h b/radio/src/datastructs.h index f5ea7944d..89c623f12 100644 --- a/radio/src/datastructs.h +++ b/radio/src/datastructs.h @@ -763,7 +763,8 @@ PACK(struct TrainerData { NOBACKUP(uint8_t spare5:1 SKIP); \ NOBACKUP(uint8_t blOffBright:7); \ NOBACKUP(char bluetoothName[LEN_BLUETOOTH_NAME]); -#elif defined(PCBTARANIS) //|| defined(PCBNV14) + #define CURR_MODEL_FILENAME +#elif defined(PCBTARANIS) #if defined(STORAGE_BLUETOOTH) #define BLUETOOTH_FIELDS \ uint8_t spare5 SKIP; \ @@ -780,10 +781,13 @@ PACK(struct TrainerData { swconfig_t switchConfig ARRAY(2,struct_switchConfig,nullptr); \ char switchNames[STORAGE_NUM_SWITCHES][LEN_SWITCH_NAME]; \ char anaNames[NUM_STICKS+STORAGE_NUM_POTS+STORAGE_NUM_SLIDERS][LEN_ANA_NAME]; \ - char currModelFilename[LEN_MODEL_FILENAME+1]; \ BLUETOOTH_FIELDS + #if defined(SDCARD_YAML) + #define CURR_MODEL_FILENAME char currModelFilename[LEN_MODEL_FILENAME+1] + #endif #else #define EXTRA_GENERAL_FIELDS + #define CURR_MODEL_FILENAME #endif #if defined(COLORLCD) && !defined(BACKUP) @@ -879,6 +883,9 @@ PACK(struct RadioData { GYRO_FIELDS NOBACKUP(int8_t uartSampleMode:2); // See UartSampleModes +#if defined(PCBTARANIS) + CURR_MODEL_FILENAME; +#endif }); #undef SWITCHES_WARNING_DATA @@ -985,19 +992,39 @@ static inline void check_struct() CHKSIZE(TrainerData, 16); #if defined(PCBXLITES) - CHKSIZE(RadioData, 861); + #if !defined(SDCARD_YAML) + CHKSIZE(RadioData, 861); + #else + CHKSIZE(RadioData, 878); + #endif CHKSIZE(ModelData, 6157); #elif defined(PCBXLITE) - CHKSIZE(RadioData, 859); + #if !defined(SDCARD_YAML) + CHKSIZE(RadioData, 859); + #else + CHKSIZE(RadioData, 876); + #endif CHKSIZE(ModelData, 6157); #elif defined(PCBX7) - CHKSIZE(RadioData, 865); + #if !defined(SDCARD_YAML) + CHKSIZE(RadioData, 865); + #else + CHKSIZE(RadioData, 882); + #endif CHKSIZE(ModelData, 6157); #elif defined(PCBX9E) - CHKSIZE(RadioData, 961); + #if !defined(SDCARD_YAML) + CHKSIZE(RadioData, 961); + #else + CHKSIZE(RadioData, 978); + #endif CHKSIZE(ModelData, 6614); #elif defined(PCBX9D) || defined(PCBX9DP) - CHKSIZE(RadioData, 899); + #if !defined(SDCARD_YAML) + CHKSIZE(RadioData, 899); + #else + CHKSIZE(RadioData, 916); + #endif CHKSIZE(ModelData, 6604); #elif defined(PCBHORUS) CHKSIZE(RadioData, 902); diff --git a/radio/src/gui/128x64/CMakeLists.txt b/radio/src/gui/128x64/CMakeLists.txt index eabf0fd51..1fe1b2fca 100644 --- a/radio/src/gui/128x64/CMakeLists.txt +++ b/radio/src/gui/128x64/CMakeLists.txt @@ -1,3 +1,9 @@ +if(${STORAGE} STREQUAL SDCARD) + set(MODEL_SELECT_SRC model_select_sd.cpp) +else() + set(MODEL_SELECT_SRC model_select.cpp) +endif() + set(GUI_SRC ${GUI_SRC} lcd.cpp @@ -5,8 +11,8 @@ set(GUI_SRC popups.cpp widgets.cpp startup_shutdown.cpp + ${MODEL_SELECT_SRC} menu_model.cpp - model_select.cpp model_setup.cpp model_failsafe.cpp model_logical_switches.cpp diff --git a/radio/src/gui/128x64/model_select_sd.cpp b/radio/src/gui/128x64/model_select_sd.cpp new file mode 100644 index 000000000..6f96aabe2 --- /dev/null +++ b/radio/src/gui/128x64/model_select_sd.cpp @@ -0,0 +1,459 @@ +/* + * Copyright (C) OpenTX + * + * Based on code named + * 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 "opentx.h" +#include "storage/modelslist.h" + + +#define CATEGORIES_WIDTH 62 +#define MODELSEL_W 62 +#define PHASE_ONE_FIRST_LINE (1 + 1 * FH) + +enum ModelSelectMode { + MODE_SELECT_MODEL, + MODE_RENAME_CATEGORY, + MODE_MOVE_MODEL, +}; + +enum ModelDeleteMode { + MODE_DELETE_MODEL, + MODE_DELETE_CATEGORY, +}; + +struct { + uint8_t selectMode, deleteMode; + ModelsCategory * currentCategory = nullptr; + int currentCategoryIndex; + int16_t subModelIndex = -1; + bool modelSelected = false; + ModelCell * currentModel = nullptr; + ModelCell * selectedModel = nullptr; + tmr10ms_t preEnterTime; + bool preEnterValid = false; + bool categorySelectMode = false; + uint16_t categoriesVerticalOffset = 0; + uint16_t categoriesVerticalPosition = 0; +} modelSelect; + +bool eeModelExists(uint8_t id) +{ + int index = 0; + + for (ModelsCategory::iterator it = modelSelect.currentCategory->begin(); it != modelSelect.currentCategory->end(); ++it, ++index) { + if (id == index){ + return true; + } + } + + return false; +} + +void setCurrentModel(unsigned int index) +{ + std::list::iterator it = modelSelect.currentCategory->begin(); + std::advance(it, index); + modelSelect.currentModel = *it; +} + +void getSelectedModel(unsigned int index) +{ + std::list::iterator it = modelSelect.currentCategory->begin(); + std::advance(it, index); + modelSelect.selectedModel = *it; +} + +void setCurrentCategory(unsigned int index) +{ + modelSelect.currentCategoryIndex = index; + const std::list& cats = modelslist.getCategories(); + std::list::const_iterator it = cats.begin(); + std::advance(it, index); + modelSelect.currentCategory = *it; + modelSelect.categoriesVerticalPosition = index; + modelSelect.categoriesVerticalOffset = limit(modelSelect.categoriesVerticalPosition - 4, modelSelect.categoriesVerticalOffset, min(modelSelect.categoriesVerticalPosition, max(0, cats.size() - 5))); +} + +void initModelsList() +{ + modelslist.load(); + + modelSelect.categoriesVerticalOffset = 0; + bool found = false; + int index = 0; + const std::list& cats = modelslist.getCategories(); + for (std::list::const_iterator it = cats.begin(); it != cats.end(); ++it, ++index) { + if (*it == modelslist.getCurrentCategory()) { + setCurrentCategory(index); + found = true; + break; + } + } + if (!found) { + setCurrentCategory(0); + } + + menuVerticalOffset = 0; + found = false; + index = 0; + for (ModelsCategory::iterator it = modelSelect.currentCategory->begin(); it != modelSelect.currentCategory->end(); ++it, ++index) { + if (*it == modelslist.getCurrentModel()) { + setCurrentModel(index); + menuVerticalPosition = index; + found = true; + break; + } + } + if (!found) { + modelslist.addModel(modelSelect.currentCategory, g_eeGeneral.currModelFilename); + setCurrentModel(0); + modelslist.setCurrentModel(modelSelect.currentModel); + modelslist.save(); + storageDirty(EE_GENERAL); + storageDirty(EE_MODEL); + storageCheck(true); + } +} + + +void onModelSelectMenu(const char * result) +{ + if (result == STR_SELECT_MODEL) { + setCurrentModel(menuVerticalPosition); + storageFlushCurrentModel(); + storageCheck(true); + memcpy(g_eeGeneral.currModelFilename, modelSelect.currentModel->modelFilename, LEN_MODEL_FILENAME); + modelslist.setCurrentModel(modelSelect.currentModel); + loadModel(g_eeGeneral.currModelFilename, true); + modelslist.setCurrentCategory(modelSelect.currentCategory); + modelslist.save(); +#if defined(INTERNAL_MODULE_CRSF) + if (g_model.moduleData[INTERNAL_MODULE].type == MODULE_TYPE_CROSSFIRE) { + crossfireTurnOnRf(); + bkregSetStatusFlag(CRSF_SET_MODEL_ID_PENDING); + } + else { + crossfireTurnOffRf(false); + } +#endif + storageDirty(EE_GENERAL); + storageCheck(true); + } + else if (result == STR_DELETE_MODEL) { + getSelectedModel(menuVerticalPosition); + POPUP_CONFIRMATION(STR_DELETEMODEL, nullptr); + SET_WARNING_INFO(modelSelect.selectedModel->modelName, LEN_MODEL_NAME, 0); + modelSelect.deleteMode = MODE_DELETE_MODEL; + } + else if (result == STR_CREATE_MODEL) { + storageCheck(true); + modelslist.addModel(modelSelect.currentCategory, createModel()); + modelSelect.selectMode = MODE_SELECT_MODEL; + setCurrentModel(modelSelect.currentCategory->size() - 1 ); + modelslist.setCurrentModel(modelSelect.currentModel); + modelslist.onNewModelCreated(modelSelect.currentModel, &g_model); + modelslist.setCurrentCategory(modelSelect.currentCategory); + modelslist.save(); +#if defined(INTERNAL_MODULE_CRSF) + if (g_model.moduleData[INTERNAL_MODULE].type == MODULE_TYPE_CROSSFIRE) { + crossfireTurnOnRf(); + bkregSetStatusFlag(CRSF_SET_MODEL_ID_PENDING); + } + else { + crossfireTurnOffRf(false); + } +#endif + storageDirty(EE_GENERAL); + storageCheck(true); + menuVerticalPosition = modelSelect.currentCategory->size() - 1; + } + else if (result == STR_DUPLICATE_MODEL) { + char duplicatedFilename[LEN_MODEL_FILENAME + 1]; + setCurrentModel(menuVerticalPosition); + memcpy(duplicatedFilename, modelSelect.currentModel->modelFilename, sizeof(duplicatedFilename)); + if (findNextFileIndex(duplicatedFilename, LEN_MODEL_FILENAME, MODELS_PATH)) { + sdCopyFile(modelSelect.currentModel->modelFilename, MODELS_PATH, duplicatedFilename, MODELS_PATH); + ModelCell* dup_model = modelslist.addModel(modelSelect.currentCategory, duplicatedFilename); + dup_model->fetchRfData(); + menuVerticalPosition = modelSelect.currentCategory->size() - 1; + } + else { + POPUP_WARNING("Invalid File"); + } + } + else if (result == STR_MOVE_MODEL) { + setCurrentModel(menuVerticalPosition); + modelSelect.selectMode = MODE_MOVE_MODEL; + modelSelect.categorySelectMode = true; + } + else if (result == STR_CREATE_CATEGORY) { + modelSelect.currentCategory = modelslist.createCategory(); + setCurrentCategory(modelslist.getCategories().size() - 1); + modelslist.save(); + storageDirty(EE_GENERAL); + storageCheck(true); + } + else if (result == STR_RENAME_CATEGORY) { + modelSelect.selectMode = MODE_RENAME_CATEGORY; + s_editMode = EDIT_MODIFY_STRING; + editNameCursorPos = 0; + } + else if (result == STR_DELETE_CATEGORY) { + if (modelSelect.currentCategory->size() > 0){ + POPUP_WARNING(STR_DELETE_ERROR); + SET_WARNING_INFO(STR_CAT_NOT_EMPTY, sizeof(TR_CAT_NOT_EMPTY), 0); + } + else { + POPUP_CONFIRMATION(STR_DELETEMODEL, nullptr); + SET_WARNING_INFO(modelSelect.currentCategory->name, LEN_MODEL_FILENAME, 0); + modelSelect.deleteMode = MODE_DELETE_CATEGORY; + } + } +} + +void menuModelSelect(event_t event) +{ + int8_t old_editMode = s_editMode; + + if (warningResult) { + warningResult = 0; + + if (modelSelect.deleteMode == MODE_DELETE_CATEGORY) { + TRACE("DELETE CATEGORY"); + modelslist.removeCategory(modelSelect.currentCategory); + modelslist.save(); + setCurrentCategory(modelSelect.currentCategoryIndex > 0 ? modelSelect.currentCategoryIndex-1 : modelSelect.currentCategoryIndex); + } + else if (modelSelect.deleteMode == MODE_DELETE_MODEL) { + int modelIndex = menuVerticalPosition; + setCurrentModel(modelIndex); + modelslist.removeModel(modelSelect.currentCategory, modelSelect.currentModel); + modelSelect.selectMode = 0; + menuVerticalPosition = modelSelect.currentCategory->size()-1; + } + } + + const std::list& cats = modelslist.getCategories(); + + title(STR_MENUMODELSEL); + drawScreenIndex(MENU_MODEL_SELECT, DIM(menuTabModel), 0); + + event_t _event_ = ((event==EVT_KEY_BREAK(KEY_ENTER) || event==EVT_KEY_LONG(KEY_ENTER)) ? 0 : event); + check_submenu_simple(_event_, modelSelect.currentCategory ? modelSelect.currentCategory->size() : 30); + + switch (event) { + case EVT_ENTRY: + modelSelect.selectMode = MODE_SELECT_MODEL; + initModelsList(); + modelSelect.preEnterValid = false; + modelSelect.categorySelectMode = false; + break; + case EVT_KEY_BREAK(KEY_ENTER): + if (modelSelect.selectMode == MODE_MOVE_MODEL) { + modelSelect.selectMode = MODE_SELECT_MODEL; + modelSelect.categorySelectMode = false; + } + killEvents(event); + break; + case EVT_KEY_FIRST(KEY_EXIT): + switch (modelSelect.selectMode) { + case MODE_MOVE_MODEL: + modelSelect.selectMode = MODE_SELECT_MODEL; + break; + } + break; + case EVT_KEY_FIRST(KEY_ENTER): + if (!modelSelect.preEnterValid) { + modelSelect.preEnterValid = true; + modelSelect.preEnterTime = get_tmr10ms(); + } + else { + modelSelect.preEnterValid = false; + modelSelect.categorySelectMode = !modelSelect.categorySelectMode; + // if (modelSelect.categorySelectMode) + // AUDIO_CATEGORY_ENABLE(); + // else + // AUDIO_CATEGORY_DISABLE(); + } + break; +#if 0 + case EVT_KEY_BREAK(KEY_PAGE): + { + if (modelSelect.categorySelectMode) { + if (modelSelect.categoriesVerticalPosition >= cats.size() - 1) + modelSelect.categoriesVerticalPosition = 0; + else + modelSelect.categoriesVerticalPosition += 1; + + if (modelSelect.selectMode == MODE_SELECT_MODEL) { + setCurrentCategory(modelSelect.categoriesVerticalPosition); + menuVerticalPosition = 0; + } + if (modelSelect.selectMode == MODE_MOVE_MODEL) { + ModelsCategory * previous_category = modelSelect.currentCategory; + ModelCell * model = modelSelect.currentModel; + setCurrentCategory(modelSelect.categoriesVerticalPosition); + modelslist.moveModel(model, previous_category, modelSelect.currentCategory); + menuVerticalPosition = modelSelect.currentCategory->size()-1; + } + + modelSelect.subModelIndex = -1; + modelSelect.modelSelected = false; + killEvents(event); + } + else { + chainMenu(menuModelSetup); + } + break; + } + + case EVT_KEY_LONG(KEY_PAGE): + { + if (modelSelect.categorySelectMode) { + if (modelSelect.categoriesVerticalPosition == 0) + modelSelect.categoriesVerticalPosition = cats.size() - 1; + else + modelSelect.categoriesVerticalPosition -= 1; + + if (modelSelect.selectMode == MODE_SELECT_MODEL) { + setCurrentCategory(modelSelect.categoriesVerticalPosition); + menuVerticalPosition = 0; + } + if (modelSelect.selectMode == MODE_MOVE_MODEL) { + ModelsCategory * previous_category = modelSelect.currentCategory; + ModelCell * model = modelSelect.currentModel; + setCurrentCategory(modelSelect.categoriesVerticalPosition); + modelslist.moveModel(model, previous_category, modelSelect.currentCategory); + } + + modelSelect.subModelIndex = -1; + modelSelect.modelSelected = false; + killEvents(event); + } + else { + chainMenu(menuTabModel[DIM(menuTabModel)-1]); + killEvents(event); + } + break; + } +#endif + case EVT_KEY_LONG(KEY_ENTER): + if (modelSelect.selectMode == MODE_SELECT_MODEL) { + killEvents(event); + if (!modelSelect.modelSelected && !modelSelect.currentCategory->empty()) { + POPUP_MENU_ADD_ITEM(STR_SELECT_MODEL); + } + POPUP_MENU_ADD_ITEM(STR_CREATE_MODEL); + if (!modelSelect.currentCategory->empty()) { + if (modelSelect.currentModel) { + POPUP_MENU_ADD_ITEM(STR_DUPLICATE_MODEL); + POPUP_MENU_ADD_ITEM(STR_MOVE_MODEL); + } + if (!modelSelect.modelSelected) { + POPUP_MENU_ADD_ITEM(STR_DELETE_MODEL); + } + } + POPUP_MENU_ADD_ITEM(STR_CREATE_CATEGORY); + POPUP_MENU_ADD_ITEM(STR_RENAME_CATEGORY); + if (cats.size() > 1) { + POPUP_MENU_ADD_ITEM(STR_DELETE_CATEGORY); + } + POPUP_MENU_START(onModelSelectMenu); + } + killEvents(event); + break; + default: + break; + } + + if (modelSelect.preEnterValid && (get_tmr10ms() - modelSelect.preEnterTime) > 50) { + modelSelect.preEnterValid = false; + } + + int index = 0; + coord_t y = 18; + + drawVerticalScrollbar(CATEGORIES_WIDTH - 1, y - 1, 4 * (FH + 7) - 5, modelSelect.categoriesVerticalOffset, cats.size(), 5); + + // Categories + for (std::list::const_iterator it = cats.begin(); it != cats.end(); ++it, ++index) { + if (index >= modelSelect.categoriesVerticalOffset && index < modelSelect.categoriesVerticalOffset + 5) { + coord_t y = MENU_HEADER_HEIGHT * 2 + 1 + (index - modelSelect.categoriesVerticalOffset) * FH * 4 / 3; + uint8_t k = index ; + + if (modelSelect.selectMode == MODE_RENAME_CATEGORY && modelSelect.currentCategory == *it) { + lcdDrawSolidFilledRect(9, y, MODELSEL_W - 1 - 9, 7); + lcdDrawRect(8, y - 1, MODELSEL_W - 1 - 7, 9, DOTTED); + editName(4, y, modelSelect.currentCategory->name, sizeof(modelSelect.currentCategory->name), event, 1, 0, old_editMode); + if (s_editMode == 0 || event == EVT_KEY_BREAK(KEY_EXIT)) { + modelslist.save(); + modelSelect.selectMode = MODE_SELECT_MODEL; + } + } + else { + lcdDrawSizedText(2, y, (*it)->name, strlen((*it)->name), ((modelSelect.categoriesVerticalPosition == k) ? INVERS : 0)); + } + if (modelSelect.selectMode == MODE_MOVE_MODEL && modelSelect.categoriesVerticalPosition == k) { + lcdDrawSolidFilledRect(9, y, MODELSEL_W - 1 - 9, 7); + lcdDrawRect(8, y - 1, MODELSEL_W - 1 - 7, 9, modelSelect.selectMode == COPY_MODE ? SOLID : DOTTED); + } + } + } + + // Models + index = 0; + bool selected = false; + bool current = false; + + for (uint8_t i = 0; i < modelSelect.currentCategory->size(); i++) { + coord_t y = MENU_HEADER_HEIGHT*2 + 1 + i*FH; + uint8_t k = i+menuVerticalOffset; + + if (k >= modelSelect.currentCategory->size()) + break; + + std::list::iterator it = modelSelect.currentCategory->begin(); + std::advance(it, k); + + selected = ((modelSelect.selectMode == MODE_SELECT_MODEL || modelSelect.selectMode == MODE_MOVE_MODEL) && k == menuVerticalPosition); + current = !strncmp((*it)->modelFilename, g_eeGeneral.currModelFilename, LEN_MODEL_FILENAME); + + if (current) { + lcdDrawChar(9 * FW + 11, y, '*'); + lcdDrawText(9 * FW + 18, y, g_model.header.name, LEADING0 | ((selected) ? INVERS : 0)); + modelSelect.subModelIndex = k; + } + else { + lcdDrawText(9 * FW + 18, y, (*it)->modelName, LEADING0 | ((selected) ? INVERS : 0)); + } + + y += 16; + + if (selected) { + lcdDrawText(5, LCD_H - FH - 1, (*it)->modelFilename, SMLSIZE); + } + } + + if (modelSelect.subModelIndex == menuVerticalPosition) { + modelSelect.modelSelected = true; + } + else { + modelSelect.modelSelected = false; + } +} + diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp index 60c2db265..68b0dd210 100644 --- a/radio/src/gui/128x64/model_setup.cpp +++ b/radio/src/gui/128x64/model_setup.cpp @@ -21,6 +21,11 @@ #include "opentx.h" +#if !defined(EEPROM) +#include "storage/sdcard_common.h" +#include "storage/modelslist.h" +#endif + // TODO find why we need this (for REGISTER at least) #if defined(PCBXLITE) #define EVT_BUTTON_PRESSED() EVT_KEY_FIRST(KEY_ENTER) @@ -1414,7 +1419,11 @@ void menuModelSetup(event_t event) } else if (event == EVT_KEY_LONG(KEY_ENTER)) { killEvents(event); +#if defined(EEPROM) uint8_t newVal = findNextUnusedModelId(g_eeGeneral.currModel, moduleIdx); +#else + uint8_t newVal = modelslist.findNextUnusedModelId(moduleIdx); +#endif if (newVal != g_model.header.modelId[moduleIdx]) { modelHeaders[g_eeGeneral.currModel].modelId[moduleIdx] = g_model.header.modelId[moduleIdx] = newVal; storageDirty(EE_MODEL); diff --git a/radio/src/gui/common/stdlcd/model_notes.cpp b/radio/src/gui/common/stdlcd/model_notes.cpp index 9eabf3153..e8388043f 100644 --- a/radio/src/gui/common/stdlcd/model_notes.cpp +++ b/radio/src/gui/common/stdlcd/model_notes.cpp @@ -25,8 +25,12 @@ void menuModelNotes(event_t event) { if (event == EVT_ENTRY) { strcpy(reusableBuffer.viewText.filename, MODELS_PATH "/"); +#if defined(EEPROM) char *buf = strcat_modelname(&reusableBuffer.viewText.filename[sizeof(MODELS_PATH)], g_eeGeneral.currModel); strcpy(buf, TEXT_EXT); +#else + strcat_currentmodelname(&reusableBuffer.viewText.filename[sizeof(MODELS_PATH)]); +#endif } menuTextView(event); diff --git a/radio/src/gui/common/stdlcd/radio_hardware.cpp b/radio/src/gui/common/stdlcd/radio_hardware.cpp index e1a7c08aa..23a8b86bb 100644 --- a/radio/src/gui/common/stdlcd/radio_hardware.cpp +++ b/radio/src/gui/common/stdlcd/radio_hardware.cpp @@ -695,6 +695,7 @@ void menuRadioHardware(event_t event) } break; +#if defined(EEPROM) case ITEM_RADIO_BACKUP_EEPROM: if (LCD_W < 212) lcdDrawText(LCD_W / 2, y, BUTTON(STR_EEBACKUP), attr | CENTERED); @@ -716,6 +717,7 @@ void menuRadioHardware(event_t event) POPUP_CONFIRMATION(STR_CONFIRMRESET, onFactoryResetConfirm); } break; +#endif } } } diff --git a/radio/src/gui/common/stdlcd/view_text.cpp b/radio/src/gui/common/stdlcd/view_text.cpp index 6c3ebff08..5dbc23c9e 100644 --- a/radio/src/gui/common/stdlcd/view_text.cpp +++ b/radio/src/gui/common/stdlcd/view_text.cpp @@ -34,8 +34,12 @@ void readModelNotes() LED_ERROR_BEGIN(); strcpy(reusableBuffer.viewText.filename, MODELS_PATH "/"); +#if defined(EEPROM) char *buf = strcat_modelname(&reusableBuffer.viewText.filename[sizeof(MODELS_PATH)], g_eeGeneral.currModel); strcpy(buf, TEXT_EXT); +#else + strcat_currentmodelname(&reusableBuffer.viewText.filename[sizeof(MODELS_PATH)]); +#endif waitKeysReleased(); event_t event = EVT_ENTRY; diff --git a/radio/src/storage/conversions/conversions.cpp b/radio/src/storage/conversions/conversions.cpp index 456420c38..8f8666cf7 100644 --- a/radio/src/storage/conversions/conversions.cpp +++ b/radio/src/storage/conversions/conversions.cpp @@ -22,7 +22,7 @@ #include "opentx.h" #include "conversions.h" -#if defined(COLORLCD) +#if defined(SDCARD_RAW) || defined(SDCARD_YAML) #include "storage/modelslist.h" #include "storage/sdcard_common.h" #include "storage/sdcard_raw.h" diff --git a/radio/src/storage/sdcard_common.cpp b/radio/src/storage/sdcard_common.cpp index b0c0de252..b2d2aadff 100644 --- a/radio/src/storage/sdcard_common.cpp +++ b/radio/src/storage/sdcard_common.cpp @@ -26,6 +26,10 @@ #include "conversions/conversions.h" #include "model_init.h" +//#if !defined(EEPROM_SDCARD) +ModelHeader modelHeaders[MAX_MODELS]; +//#endif + // defined either in sdcard_raw.cpp or sdcard_yaml.cpp void storageCreateModelsList(); @@ -183,3 +187,19 @@ void storageReadAll() } } +void checkModelIdUnique(uint8_t index, uint8_t module) +{ + if (isModuleXJTD8(module)) + return; + + char * warn_buf = reusableBuffer.moduleSetup.msg; + + // cannot rely exactly on WARNING_LINE_LEN so using WARNING_LINE_LEN-2 + size_t warn_buf_len = sizeof(reusableBuffer.moduleSetup.msg) - WARNING_LINE_LEN - 2; + if (!modelslist.isModelIdUnique(module,warn_buf,warn_buf_len)) { + if (warn_buf[0] != 0) { + POPUP_WARNING(STR_MODELIDUSED); + SET_WARNING_INFO(warn_buf, sizeof(reusableBuffer.moduleSetup.msg), 0); + } + } +} diff --git a/radio/src/storage/sdcard_common.h b/radio/src/storage/sdcard_common.h index 04673ef2d..fb3d6192c 100644 --- a/radio/src/storage/sdcard_common.h +++ b/radio/src/storage/sdcard_common.h @@ -34,6 +34,10 @@ #define MODEL_FILENAME_PATTERN "model.yml" #endif +//#if !defined(EEPROM) +extern ModelHeader modelHeaders[MAX_MODELS]; +//#endif + // opens radio.bin or model file const char* openFileBin(const char* fullpath, FIL* file, uint16_t* size, uint8_t* version); @@ -53,4 +57,7 @@ const char * writeGeneralSettings(); const char * loadRadioSettings(const char * path); const char * loadRadioSettings(); + +void checkModelIdUnique(uint8_t index, uint8_t module); + #endif // _SDCARD_RAW_H_ diff --git a/radio/src/storage/yaml/yaml_datastructs_x7.cpp b/radio/src/storage/yaml/yaml_datastructs_x7.cpp index ac621d122..fc2de09a6 100644 --- a/radio/src/storage/yaml/yaml_datastructs_x7.cpp +++ b/radio/src/storage/yaml/yaml_datastructs_x7.cpp @@ -261,8 +261,7 @@ static const struct YamlNode struct_RadioData[] = { YAML_UNSIGNED( "adjustRTC", 1 ), YAML_UNSIGNED( "inactivityTimer", 8 ), YAML_UNSIGNED( "telemetryBaudrate", 3 ), - YAML_UNSIGNED( "splashMode", 1 ), - YAML_PADDING( 2 ), + YAML_SIGNED( "splashMode", 3 ), YAML_SIGNED( "hapticMode", 2 ), YAML_SIGNED( "switchesDelay", 8 ), YAML_UNSIGNED( "lightAutoOff", 8 ), @@ -310,6 +309,8 @@ static const struct YamlNode struct_RadioData[] = { YAML_PADDING( 8 ), YAML_STRING("bluetoothName", 10), YAML_STRING("ownerRegistrationID", 8), + YAML_SIGNED( "uartSampleMode", 2 ), + YAML_STRING("currModelFilename", 17), YAML_END }; static const struct YamlNode struct_unsigned_8[] = {