1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-23 16:25:16 +03:00
opentx/radio/src/storage/sdcard_raw.cpp
Damjan Adamic baacc0fe29 Stick mode now in one global variable, it should work in Horus emerge… (#3455)
* Stick mode now in one global variable, it should work in Horus emergency mode

* Improvements (suggested by Bertrand)
2016-05-02 23:39:15 +02:00

252 lines
5.7 KiB
C++

/*
* 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"
void getModelPath(char * path, const char * filename)
{
strcpy(path, STR_MODELS_PATH);
path[sizeof(MODELS_PATH)-1] = '/';
strcpy(&path[sizeof(MODELS_PATH)], filename);
}
const char * writeFile(const char * filename, const uint8_t * data, uint16_t size)
{
FIL file;
char buf[8];
UINT written;
FRESULT result = f_open(&file, filename, FA_CREATE_ALWAYS | FA_WRITE);
if (result != FR_OK) {
return SDCARD_ERROR(result);
}
*(uint32_t*)&buf[0] = O9X_FOURCC;
buf[4] = EEPROM_VER;
buf[5] = 'M';
*(uint16_t*)&buf[6] = size;
result = f_write(&file, buf, 8, &written);
if (result != FR_OK || written != 8) {
f_close(&file);
return SDCARD_ERROR(result);
}
result = f_write(&file, data, size, &written);
if (result != FR_OK || written != size) {
f_close(&file);
return SDCARD_ERROR(result);
}
f_close(&file);
return NULL;
}
const char * writeModel()
{
char path[256];
getModelPath(path, g_eeGeneral.currModelFilename);
return writeFile(path, (uint8_t *)&g_model, sizeof(g_model));
}
const char * loadFile(const char * filename, uint8_t * data, uint16_t maxsize)
{
FIL file;
char buf[8];
UINT read;
FRESULT result = f_open(&file, filename, FA_OPEN_EXISTING | FA_READ);
if (result != FR_OK) {
return SDCARD_ERROR(result);
}
if (f_size(&file) < 8) {
f_close(&file);
return STR_INCOMPATIBLE;
}
result = f_read(&file, (uint8_t *)buf, 8, &read);
if (result != FR_OK || read != 8) {
f_close(&file);
return SDCARD_ERROR(result);
}
uint8_t version = (uint8_t)buf[4];
if (*(uint32_t*)&buf[0] != O9X_FOURCC || version < FIRST_CONV_EEPROM_VER || version > EEPROM_VER || buf[5] != 'M') {
f_close(&file);
return STR_INCOMPATIBLE;
}
uint16_t size = min<uint16_t>(maxsize, *(uint16_t*)&buf[6]);
result = f_read(&file, data, size, &read);
if (result != FR_OK || read != size) {
f_close(&file);
return SDCARD_ERROR(result);
}
f_close(&file);
return NULL;
}
const char * readModel(const char * filename, uint8_t * buffer, uint32_t size)
{
char path[256];
getModelPath(path, filename);
return loadFile(path, buffer, size);
}
const char * loadModel(const char * filename)
{
preModelLoad();
const char * error = readModel(filename, (uint8_t *)&g_model, sizeof(g_model));
if (error) {
TRACE("loadModel error=%s", error);
}
bool newModel = false;
if (error) {
modelDefault(0) ;
storageCheck(true);
newModel = true;
}
postModelLoad(newModel);
return error;
}
const char * loadGeneralSettings()
{
const char * error = loadFile(RADIO_SETTINGS_PATH, (uint8_t *)&g_eeGeneral, sizeof(g_eeGeneral));
if (error) {
TRACE("loadGeneralSettings error=%s", error);
}
// TODO this is temporary, we only have one model for now
return error;
}
const char * writeGeneralSettings()
{
return writeFile(RADIO_SETTINGS_PATH, (uint8_t *)&g_eeGeneral, sizeof(g_eeGeneral));
}
void storageCheck(bool immediately)
{
if (storageDirtyMsk & EE_GENERAL) {
TRACE("eeprom write general");
storageDirtyMsk -= EE_GENERAL;
const char * error = writeGeneralSettings();
if (error) {
TRACE("writeGeneralSettings error=%s", error);
}
}
if (storageDirtyMsk & EE_MODEL) {
TRACE("eeprom write model");
storageDirtyMsk -= EE_MODEL;
const char * error = writeModel();
if (error) {
TRACE("writeModel error=%s", error);
}
}
}
void storageReadAll()
{
sdInit();
if (loadGeneralSettings() != NULL) {
storageEraseAll(true);
}
#if defined(CPUARM)
for (uint8_t i=0; languagePacks[i]!=NULL; i++) {
if (!strncmp(g_eeGeneral.ttsLanguage, languagePacks[i]->id, 2)) {
currentLanguagePackIdx = i;
currentLanguagePack = languagePacks[i];
}
}
#endif
loadModel(g_eeGeneral.currModelFilename);
}
void storageCreateModelsList()
{
FIL file;
FRESULT result = f_open(&file, RADIO_MODELSLIST_PATH, FA_CREATE_ALWAYS | FA_WRITE);
if (result == FR_OK) {
f_puts("[" DEFAULT_CATEGORY "]\n" DEFAULT_MODEL_FILENAME "\n", &file);
f_close(&file);
}
}
void storageFormat()
{
sdCheckAndCreateDirectory(RADIO_PATH);
sdCheckAndCreateDirectory(MODELS_PATH);
storageCreateModelsList();
}
const char * createModel()
{
preModelLoad();
char filename[LEN_MODEL_FILENAME+1];
memset(filename, 0, sizeof(filename));
strcpy(filename, "model.bin");
int index = findNextFileIndex(filename, MODELS_PATH);
if (index > 0) {
modelDefault(index);
memcpy(g_eeGeneral.currModelFilename, filename, sizeof(g_eeGeneral.currModelFilename));
storageDirty(EE_GENERAL);
storageDirty(EE_MODEL);
storageCheck(true);
}
postModelLoad(true);
return g_eeGeneral.currModelFilename;
}
void storageEraseAll(bool warn)
{
TRACE("storageEraseAll()");
#if defined(COLORLCD)
// the theme has not been loaded before
theme->load();
#endif
generalDefault();
modelDefault(1);
if (warn) {
ALERT(STR_STORAGE_WARNING, STR_BAD_RADIO_DATA, AU_BAD_RADIODATA);
}
MESSAGE(STR_STORAGE_WARNING, STR_STORAGE_FORMAT, NULL, AU_NONE);
storageFormat();
storageDirty(EE_GENERAL|EE_MODEL);
storageCheck(true);
}