306 lines
7.4 KiB
C++
306 lines
7.4 KiB
C++
/*
|
|
* 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 "opentx.h"
|
|
#include "conversions.h"
|
|
|
|
#if defined(SDCARD_RAW) || defined(SDCARD_YAML)
|
|
#include "storage/modelslist.h"
|
|
#include "storage/sdcard_common.h"
|
|
#include "storage/sdcard_raw.h"
|
|
#include "storage/sdcard_yaml.h"
|
|
#endif
|
|
|
|
#if defined(STORAGE_MODELSLIST)
|
|
static void drawProgressScreen(const char* filename, int progress, int total)
|
|
{
|
|
#if defined(COLORLCD)
|
|
OpenTxTheme* l_theme = static_cast<OpenTxTheme*>(theme);
|
|
|
|
lcd->reset();
|
|
l_theme->drawBackground(lcd);
|
|
lcd->drawText(LCD_W/2, LCD_H/2 - 30, STR_CONVERTING, FONT(XL) | CENTERED | COLOR_THEME_WARNING);
|
|
lcd->drawText(LCD_W/2, LCD_H/2, filename, FONT(STD) | CENTERED | COLOR_THEME_SECONDARY1);
|
|
|
|
l_theme->drawProgressBar(lcd,
|
|
LCD_W / 4,
|
|
LCD_H / 2 + 40,
|
|
LCD_W / 2,
|
|
20,
|
|
progress, total);
|
|
|
|
WDG_RESET();
|
|
lcdRefresh();
|
|
#else
|
|
// TODO: BW progress screen
|
|
#endif
|
|
}
|
|
|
|
void convertBinRadioData(const char * path, int version)
|
|
{
|
|
TRACE("convertRadioData(%s,%d)", path, version);
|
|
|
|
#if defined(COLORLCD)
|
|
// the theme has not been loaded before
|
|
static_cast<OpenTxTheme*>(theme)->load();
|
|
|
|
// Init backlight mode before entering alert screens
|
|
requiredBacklightBright = BACKLIGHT_FORCED_ON;
|
|
g_eeGeneral.blOffBright = 20;
|
|
#endif
|
|
|
|
RAISE_ALERT(STR_STORAGE_WARNING, STR_SDCARD_CONVERSION_REQUIRE, NULL,
|
|
AU_NONE);
|
|
|
|
// Load models list before converting
|
|
modelslist.load(ModelsList::Format::txt);
|
|
|
|
unsigned converted = 0;
|
|
auto to_convert = modelslist.getModelsCount() + 1;
|
|
|
|
drawProgressScreen(RADIO_FILENAME, converted, to_convert);
|
|
TRACE("converting '%s' (%d/%d)", RADIO_FILENAME, converted, to_convert);
|
|
|
|
#if STORAGE_CONVERSIONS < 220
|
|
if (version == 219) {
|
|
convertRadioData_219_to_220(path);
|
|
version = 220;
|
|
}
|
|
#endif
|
|
#if STORAGE_CONVERSIONS < 220
|
|
if (version == 220) {
|
|
convertRadioData_220_to_221(path);
|
|
version = 221;
|
|
}
|
|
#endif
|
|
converted++;
|
|
|
|
#if defined(SIMU)
|
|
RTOS_WAIT_MS(200);
|
|
#endif
|
|
|
|
const char* error = nullptr;
|
|
for (auto category_ptr : modelslist.getCategories()) {
|
|
|
|
auto model_it = category_ptr->begin();
|
|
|
|
while(model_it != category_ptr->end()) {
|
|
|
|
uint8_t model_version = 0;
|
|
auto* model_ptr = *model_it;
|
|
char* filename = model_ptr->modelFilename;
|
|
|
|
TRACE("converting '%s' (%d/%d)", filename, converted, to_convert);
|
|
drawProgressScreen(filename, converted, to_convert);
|
|
|
|
// read only the version number (size=0)
|
|
error = readModelBin(filename, nullptr, 0, &model_version);
|
|
if (!error) {
|
|
// TODO: error handling
|
|
error = convertBinModelData(filename, model_version);
|
|
++model_it;
|
|
|
|
if (error) {
|
|
TRACE("ERROR converting '%s': %s", filename, error);
|
|
category_ptr->removeModel(model_ptr);
|
|
} else {
|
|
PartialModel partial;
|
|
memclear(&partial, sizeof(PartialModel));
|
|
|
|
readModelYaml(filename, reinterpret_cast<uint8_t*>(&partial), sizeof(partial));
|
|
model_ptr->setModelName(partial.header.name);
|
|
}
|
|
} else {
|
|
TRACE("ERROR reading '%s': %s", filename, error);
|
|
|
|
// remove that file from the models list
|
|
++model_it;
|
|
category_ptr->removeModel(model_ptr);
|
|
}
|
|
|
|
converted++;
|
|
|
|
#if defined(SIMU)
|
|
RTOS_WAIT_MS(200);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#if defined(SDCARD_YAML) || defined(STORAGE_MODELSLIST)
|
|
modelslist.save();
|
|
// trigger models list reload
|
|
modelslist.clear();
|
|
#endif
|
|
}
|
|
|
|
void patchFilenameToYaml(char* str)
|
|
{
|
|
constexpr unsigned bin_len = sizeof(MODELS_EXT) - 1;
|
|
constexpr unsigned yml_len = sizeof(YAML_EXT) - 1;
|
|
|
|
// patch file extension
|
|
const char* ext = strrchr(str, '.');
|
|
if (ext && (strlen(ext) == bin_len) &&
|
|
!strncmp(ext, STR_MODELS_EXT, bin_len)) {
|
|
memcpy((void*)ext, (void*)STR_YAML_EXT, yml_len + 1);
|
|
}
|
|
}
|
|
|
|
const char* convertBinModelData(char* filename, int version)
|
|
{
|
|
TRACE("convertModelData(%s)", filename);
|
|
|
|
char path[FF_MAX_LFN + 1];
|
|
memcpy(path, MODELS_PATH, sizeof(MODELS_PATH)-1);
|
|
path[sizeof(MODELS_PATH)-1] = '/';
|
|
strcpy(&path[sizeof(MODELS_PATH)], filename);
|
|
|
|
#if STORAGE_CONVERSIONS < 220
|
|
if (version == 219) {
|
|
const char* error = convertModelData_219_to_220(path);
|
|
if (error) return error;
|
|
version = 220;
|
|
}
|
|
#endif
|
|
#if STORAGE_CONVERSIONS < 221
|
|
if (version == 220) {
|
|
const char* error = convertModelData_220_to_221(path);
|
|
if (error) return error;
|
|
version = 221;
|
|
}
|
|
#endif
|
|
|
|
patchFilenameToYaml(filename);
|
|
return nullptr;
|
|
}
|
|
#endif
|
|
|
|
#if defined(EEPROM) || defined(EEPROM_RLC)
|
|
#include "storage/eeprom_common.h"
|
|
|
|
void eeConvertModel(int id, int version)
|
|
{
|
|
TRACE("eeConvertModel(%d,%d)", id, version);
|
|
|
|
#if STORAGE_CONVERSIONS < 220
|
|
if (version == 219) {
|
|
convertModelData_219_to_220(id);
|
|
version = 220;
|
|
}
|
|
#endif
|
|
#if STORAGE_CONVERSIONS < 221
|
|
if (version == 220) {
|
|
convertModelData_220_to_221(id);
|
|
version = 221;
|
|
}
|
|
#endif
|
|
// TODO: error handling
|
|
}
|
|
|
|
bool eeConvert()
|
|
{
|
|
const char *msg = NULL;
|
|
|
|
switch (g_eeGeneral.version) {
|
|
case 219:
|
|
msg = "EEprom Data v219";
|
|
break;
|
|
case 220:
|
|
msg = "EEprom Data v220";
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
int conversionVersionStart = g_eeGeneral.version;
|
|
|
|
// Information to the user and wait for key press
|
|
g_eeGeneral.backlightMode = e_backlight_mode_on;
|
|
g_eeGeneral.backlightBright = 0;
|
|
g_eeGeneral.contrast = 25;
|
|
|
|
ALERT(STR_STORAGE_WARNING, msg, AU_BAD_RADIODATA);
|
|
|
|
RAISE_ALERT(STR_STORAGE_WARNING, STR_EEPROM_CONVERTING, NULL, AU_NONE);
|
|
|
|
// General Settings conversion
|
|
int version = conversionVersionStart;
|
|
|
|
sdCheckAndCreateDirectory(RADIO_PATH);
|
|
sdCheckAndCreateDirectory(MODELS_PATH);
|
|
|
|
#if STORAGE_CONVERSIONS < 220
|
|
if (version == 219) {
|
|
version = 220;
|
|
convertRadioData_219_to_220();
|
|
}
|
|
#endif
|
|
#if STORAGE_CONVERSIONS < 221
|
|
if (version == 220) {
|
|
version = 221;
|
|
convertRadioData_220_to_221();
|
|
}
|
|
#endif
|
|
//TODO: reload from YAML
|
|
g_eeGeneral.version = EEPROM_VER;
|
|
// storageDirty(EE_GENERAL);
|
|
// storageCheck(true);
|
|
|
|
#if defined(STORAGE_MODELSLIST)
|
|
modelslist.clear();
|
|
#endif
|
|
|
|
#if LCD_W >= 212
|
|
lcdDrawRect(60, 6*FH+4, 132, 3);
|
|
#else
|
|
lcdDrawRect(10, 6*FH+4, 102, 3);
|
|
#endif
|
|
|
|
// Models conversion
|
|
for (uint8_t id=0; id<MAX_MODELS; id++) {
|
|
#if LCD_W >= 212
|
|
lcdDrawSolidHorizontalLine(61, 6*FH+5, 10+id*2, FORCE);
|
|
#else
|
|
lcdDrawSolidHorizontalLine(11, 6*FH+5, 10+(id*3)/2, FORCE);
|
|
#endif
|
|
lcdRefresh();
|
|
|
|
#if defined(SIMU)
|
|
RTOS_WAIT_MS(100);
|
|
#endif
|
|
|
|
#if defined(SDCARD_RAW) || defined(SDCARD_YAML)
|
|
if (eeModelExistsRlc(id)) {
|
|
#else
|
|
if (eeModelExists(id)) {
|
|
#endif
|
|
eeConvertModel(id, conversionVersionStart);
|
|
}
|
|
}
|
|
|
|
#if defined(STORAGE_MODELSLIST)
|
|
modelslist.save();
|
|
#endif
|
|
|
|
return true;
|
|
}
|
|
#endif
|