1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-26 09:45:21 +03:00

Directory transmitter renamed to radio

This commit is contained in:
Bertrand Songis 2013-12-02 07:13:57 +01:00
parent f4df52a033
commit 942e658c8e
707 changed files with 0 additions and 0 deletions

809
radio/src/eeprom_raw.cpp Normal file
View file

@ -0,0 +1,809 @@
/*
* Authors (alphabetical order)
* - Andre Bernet <bernet.andre@gmail.com>
* - Andreas Weitl
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
* - Cameron Weeks <th9xer@gmail.com>
* - Erez Raviv
* - Gabriel Birkus
* - Jean-Pierre Parisy
* - Karl Szmutny
* - Michael Blandford
* - Michal Hlavinka
* - Pat Mackenzie
* - Philip Moss
* - Rob Thomson
* - Romolo Manfredini <romolo.manfredini@gmail.com>
* - 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 <stdint.h>
#include "opentx.h"
#include "inttypes.h"
#include "string.h"
volatile uint32_t Spi_complete; // TODO in the driver ?
// Logic for storing to EEPROM/loading from EEPROM
// If main needs to wait for the eeprom, call mainsequence without actioning menus
// General configuration
// 'main' set flag STORE_GENERAL
// 'eeCheck' sees flag STORE_GENERAL, copies data, starts 2 second timer, clears flag STORE_GENERAL
// 'eeCheck' sees 2 second timer expire, locks copy, initiates write, enters WRITE_GENERAL mode
// 'eeCheck' completes write, unlocks copy, exits WRITE_GENERAL mode
// 'main' set flag STORE_MODEL(n)
// 'main' set flag STORE_MODEL_TRIM(n)
// 'main' needs to load a model
// These may not be needed, or might just be smaller
// TODO in the driver ?
uint8_t Spi_tx_buf[24] ;
uint8_t Spi_rx_buf[24] ;
struct t_file_entry File_system[MAX_MODELS+1] ;
// TODO check everything here
uint8_t Eeprom32_process_state = E32_IDLE;
uint8_t Eeprom32_state_after_erase ;
uint8_t Eeprom32_write_pending ;
uint8_t Eeprom32_file_index ;
uint8_t *Eeprom32_buffer_address ;
uint8_t *Eeprom32_source_address ;
uint32_t Eeprom32_address ;
uint32_t Eeprom32_data_size ;
#define EE_NOWAIT 1
uint32_t get_current_block_number( uint32_t block_no, uint16_t *p_size, uint32_t *p_seq ) ;
void write32_eeprom_block( uint32_t eeAddress, register uint8_t *buffer, uint32_t size, uint32_t immediate=0 ) ;
// New file system
// Start with 16 model memories, initial test uses 34 and 35 for these
// Blocks 0 and 1, general
// Blocks 2 and 3, model 1
// Blocks 4 and 5, model 2 etc
// Blocks 32 and 33, model 16
uint8_t Current_general_block ; // 0 or 1 is active block
uint8_t Other_general_block_blank ;
struct t_eeprom_buffer
{
struct t_eeprom_header header ;
union t_eeprom_data
{
EEGeneral general_data ;
ModelData model_data ;
uint8_t bytes[4096-sizeof(t_eeprom_header)];
} data ;
} Eeprom_buffer ;
void eeDeleteModel(uint8_t id)
{
eeCheck(true);
memset(modelHeaders[id].name, 0, sizeof(g_model.header.name));
Eeprom32_source_address = (uint8_t *)&g_model ; // Get data from here
Eeprom32_data_size = 0 ; // This much
Eeprom32_file_index = id + 1 ; // This file system entry
Eeprom32_process_state = E32_BLANKCHECK ;
eeWaitFinished();
}
bool eeCopyModel(uint8_t dst, uint8_t src)
{
// eeCheck(true) should have been called before entering here
uint16_t size = File_system[src+1].size ;
read32_eeprom_data( (File_system[src+1].block_no << 12) + sizeof( struct t_eeprom_header), ( uint8_t *)&Eeprom_buffer.data.model_data, size) ;
if (size > sizeof(g_model.header.name))
memcpy(modelHeaders[dst].name, Eeprom_buffer.data.model_data.header.name, sizeof(g_model.header.name));
else
memset(modelHeaders[dst].name, 0, sizeof(g_model.header.name));
Eeprom32_source_address = (uint8_t *)&Eeprom_buffer.data.model_data; // Get data from here
Eeprom32_data_size = sizeof(g_model) ; // This much
Eeprom32_file_index = dst + 1 ; // This file system entry
Eeprom32_process_state = E32_BLANKCHECK ;
eeWaitFinished();
return true;
}
void eeSwapModels(uint8_t id1, uint8_t id2)
{
// eeCheck(true) should have been called before entering here
uint16_t id2_size = File_system[id2+1].size;
uint32_t id2_block_no = File_system[id2+1].block_no;
eeCopyModel(id2, id1);
// block_no(id1) has been shifted now, but we have the size
// TODO flash saving with function above ...
if (id2_size > sizeof(g_model.header.name)) {
read32_eeprom_data( (id2_block_no << 12) + sizeof( struct t_eeprom_header), ( uint8_t *)&Eeprom_buffer.data.model_data, id2_size);
memcpy(modelHeaders[id1].name, Eeprom_buffer.data.model_data.header.name, sizeof(g_model.header.name));
}
else {
memset(modelHeaders[id1].name, 0, sizeof(g_model.header.name));
}
Eeprom32_source_address = (uint8_t *)&Eeprom_buffer.data.model_data; // Get data from here
Eeprom32_data_size = id2_size ; // This much
Eeprom32_file_index = id1 + 1 ; // This file system entry
Eeprom32_process_state = E32_BLANKCHECK ;
eeWaitFinished();
}
// Read eeprom data starting at random address
void read32_eeprom_data(uint32_t eeAddress, register uint8_t *buffer, uint32_t size, uint32_t immediate)
{
#ifdef SIMU
assert(size);
eeprom_pointer = eeAddress;
eeprom_buffer_data = (char*)buffer;
eeprom_buffer_size = size;
eeprom_read_operation = true;
Spi_complete = false;
sem_post(eeprom_write_sem);
#else
register uint8_t *p = Spi_tx_buf ;
*p = 3 ; // Read command
*(p+1) = eeAddress >> 16 ;
*(p+2) = eeAddress >> 8 ;
*(p+3) = eeAddress ; // 3 bytes address
spi_PDC_action( p, 0, buffer, 4, size ) ;
#endif
if (immediate )
return ;
while (!Spi_complete) {
#ifdef SIMU
sleep(5/*ms*/);
#endif
}
}
void write32_eeprom_block( uint32_t eeAddress, register uint8_t *buffer, uint32_t size, uint32_t immediate )
{
#ifdef SIMU
assert(size);
eeprom_pointer = eeAddress;
eeprom_buffer_data = (char*)buffer;
eeprom_buffer_size = size+1;
eeprom_read_operation = false;
Spi_complete = false;
sem_post(eeprom_write_sem);
#else
eeprom_write_enable();
register uint8_t *p = Spi_tx_buf;
*p = 2; // Write command
*(p + 1) = eeAddress >> 16;
*(p + 2) = eeAddress >> 8;
*(p + 3) = eeAddress; // 3 bytes address
spi_PDC_action(p, buffer, 0, 4, size);
#endif
if (immediate)
return;
while (!Spi_complete) {
#ifdef SIMU
sleep(5/*ms*/);
#endif
}
}
uint8_t byte_checksum( uint8_t *p, uint32_t size )
{
uint32_t csum ;
csum = 0 ;
while( size )
{
csum += *p++ ;
size -= 1 ;
}
return csum ;
}
uint32_t ee32_check_header( struct t_eeprom_header *hptr )
{
uint8_t csum ;
csum = byte_checksum( ( uint8_t *) hptr, 7 ) ;
if ( csum == hptr->hcsum )
{
return 1 ;
}
return 0 ;
}
// Pass in an even block number, this and the next block will be checked
// to see which is the most recent, the block_no of the most recent
// is returned, with the corresponding data size if required
// and the sequence number if required
uint32_t get_current_block_number( uint32_t block_no, uint16_t *p_size, uint32_t *p_seq )
{
struct t_eeprom_header b0 ;
struct t_eeprom_header b1 ;
uint32_t sequence_no ;
uint16_t size ;
read32_eeprom_data( block_no << 12, ( uint8_t *)&b0, sizeof(b0) ) ; // Sequence # 0
read32_eeprom_data( (block_no+1) << 12, ( uint8_t *)&b1, sizeof(b1) ) ; // Sequence # 1
if ( ee32_check_header( &b0 ) == 0 )
{
b0.sequence_no = 0 ;
b0.data_size = 0 ;
b0.flags = 0 ;
}
size = b0.data_size ;
sequence_no = b0.sequence_no ;
if ( ee32_check_header( &b0 ) == 0 )
{
if ( ee32_check_header( &b1 ) != 0 )
{
size = b1.data_size ;
sequence_no = b1.sequence_no ;
block_no += 1 ;
}
else
{
size = 0 ;
sequence_no = 1 ;
}
}
else
{
if ( ee32_check_header( &b1 ) != 0 )
{
if ( b1.sequence_no > b0.sequence_no )
{
size = b1.data_size ;
sequence_no = b1.sequence_no ;
block_no += 1 ;
}
}
}
if ( size == 0xFFFF )
{
size = 0 ;
}
if ( p_size )
{
*p_size = size ;
}
if ( sequence_no == 0xFFFFFFFF )
{
sequence_no = 0 ;
}
if ( p_seq )
{
*p_seq = sequence_no ;
}
// Block_needs_erasing = erase ;
return block_no ;
}
bool eeLoadGeneral()
{
uint16_t size = File_system[0].size;
memset(&g_eeGeneral, 0, sizeof(EEGeneral));
if (size > sizeof(EEGeneral)) {
size = sizeof(EEGeneral) ;
}
if (size) {
read32_eeprom_data( ( File_system[0].block_no << 12) + sizeof( struct t_eeprom_header), ( uint8_t *)&g_eeGeneral, size) ;
}
if (g_eeGeneral.version != EEPROM_VER) {
TRACE("EEPROM version %d instead of %d", g_eeGeneral.version, EEPROM_VER);
if (!eeConvert())
return false;
}
return true;
}
void eeLoadModel(uint8_t id)
{
if (id<MAX_MODELS) {
#if defined(SDCARD)
closeLogs();
#endif
if (pulsesStarted()) {
pausePulses();
}
pauseMixerCalculations();
uint16_t size = File_system[id+1].size ;
memset(&g_model, 0, sizeof(g_model));
#if defined(SIMU)
if (size > 0 && size != sizeof(g_model)) {
printf("Model data read=%d bytes vs %d bytes\n", size, (int)sizeof(ModelData));
}
#endif
if (size > sizeof(g_model)) {
size = sizeof(g_model) ;
}
if(size < 256) { // if not loaded a fair amount
modelDefault(id) ;
eeCheck(true);
}
else {
read32_eeprom_data((File_system[id+1].block_no << 12) + sizeof(struct t_eeprom_header), (uint8_t *)&g_model, size) ;
}
resetAll();
if (pulsesStarted()) {
checkAll();
resumePulses();
}
activeSwitches = 0;
activeFnSwitches = 0;
activeFunctions = 0;
memclear(lastFunctionTime, sizeof(lastFunctionTime));
#if defined(CPUARM)
evalFunctionsFirstTime = true;
#endif
for (uint8_t i=0; i<MAX_TIMERS; i++) {
if (g_model.timers[i].persistent) {
timersStates[i].val = g_model.timers[i].value;
}
}
resumeMixerCalculations();
// TODO pulses should be started after mixer calculations ...
#if defined(FRSKY)
frskySendAlarms();
#endif
#if defined(CPUARM) && defined(SDCARD)
refreshModelAudioFiles();
#endif
LOAD_MODEL_BITMAP();
SEND_FAILSAFE_1S();
}
}
bool eeModelExists(uint8_t id)
{
return ( File_system[id+1].size > 0 ) ;
}
void eeLoadModelName(uint8_t id, char *name)
{
memclear(name, sizeof(g_model.header.name));
if (id < MAX_MODELS) {
id += 1;
if (File_system[id].size > sizeof(g_model.header.name) ) {
read32_eeprom_data((File_system[id].block_no << 12)+8, (uint8_t *)name, sizeof(g_model.header.name));
}
}
}
#if defined(CPUARM)
void eeLoadModelHeader(uint8_t id, ModelHeader *header)
{
memclear(header, sizeof(ModelHeader));
if (id < MAX_MODELS) {
id += 1;
if (File_system[id].size > sizeof(ModelHeader)) {
read32_eeprom_data((File_system[id].block_no << 12)+8, (uint8_t *)header, sizeof(ModelHeader));
}
}
}
#endif
void fill_file_index()
{
for (uint32_t i = 0 ; i < MAX_MODELS + 1 ; i += 1 )
{
File_system[i].block_no = get_current_block_number( i * 2, &File_system[i].size, &File_system[i].sequence_no ) ;
}
}
void eeReadAll()
{
fill_file_index() ;
if (!eeLoadGeneral() )
{
generalDefault();
modelDefault(0);
ALERT(STR_EEPROMWARN, STR_BADEEPROMDATA, AU_BAD_EEPROM);
MESSAGE(STR_EEPROMWARN, STR_EEPROMFORMATTING, NULL, AU_EEPROM_FORMATTING);
/* we remove all models */
for (uint32_t i=0; i<MAX_MODELS; i++)
eeDeleteModel(i);
eeDirty(EE_GENERAL);
eeDirty(EE_MODEL);
}
else {
eeLoadModelHeaders() ;
}
// TODO common!
stickMode = g_eeGeneral.stickMode;
#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
}
void eeWaitFinished()
{
while (Eeprom32_process_state != E32_IDLE) {
ee32_process();
#ifdef SIMU
sleep(5/*ms*/);
#endif
}
}
void eeCheck(bool immediately)
{
if (immediately) {
eeWaitFinished();
}
if (s_eeDirtyMsk & EE_GENERAL) {
s_eeDirtyMsk -= EE_GENERAL;
Eeprom32_source_address = (uint8_t *)&g_eeGeneral ; // Get data from here
Eeprom32_data_size = sizeof(g_eeGeneral) ; // This much
Eeprom32_file_index = 0 ; // This file system entry
Eeprom32_process_state = E32_BLANKCHECK ;
if (immediately)
eeWaitFinished();
else
return;
}
if (s_eeDirtyMsk & EE_MODEL) {
s_eeDirtyMsk -= EE_MODEL;
Eeprom32_source_address = (uint8_t *)&g_model ; // Get data from here
Eeprom32_data_size = sizeof(g_model) ; // This much
Eeprom32_file_index = g_eeGeneral.currModel + 1 ; // This file system entry
Eeprom32_process_state = E32_BLANKCHECK ;
if (immediately)
eeWaitFinished();
}
}
void ee32_process()
{
register uint8_t *p ;
register uint8_t *q ;
register uint32_t x ;
register uint32_t eeAddress ;
if ( Eeprom32_process_state == E32_BLANKCHECK ) {
eeAddress = File_system[Eeprom32_file_index].block_no ^ 1 ;
eeAddress <<= 12 ; // Block start address
Eeprom32_address = eeAddress ; // Where to put new data
#if 0
x = Eeprom32_data_size + sizeof( struct t_eeprom_header ) ; // Size needing to be checked
p = (uint8_t *) &Eeprom_buffer ;
read32_eeprom_data( eeAddress, p, x, EE_NOWAIT ) ;
#endif
Eeprom32_process_state = E32_READSENDING ;
}
if ( Eeprom32_process_state == E32_READSENDING )
{
#if 0
if ( Spi_complete )
{
uint32_t blank = 1 ;
x = Eeprom32_data_size + sizeof( struct t_eeprom_header ) ; // Size needing to be checked
p = (uint8_t *) &Eeprom_buffer ;
while ( x )
{
if ( *p++ != 0xFF )
{
blank = 0 ;
break ;
}
x -= 1 ;
}
// If not blank, sort erasing here
if ( blank )
{
Eeprom32_state_after_erase = E32_IDLE ; // TODO really needed?
Eeprom32_process_state = E32_WRITESTART ;
}
else
{
#endif
#ifdef SIMU
Eeprom32_process_state = E32_WRITESTART ;
#else
eeAddress = Eeprom32_address ;
eeprom_write_enable() ;
p = Spi_tx_buf ;
*p = 0x20 ; // Block Erase command
*(p+1) = eeAddress >> 16 ;
*(p+2) = eeAddress >> 8 ;
*(p+3) = eeAddress ; // 3 bytes address
spi_PDC_action( p, 0, 0, 4, 0 ) ;
Eeprom32_process_state = E32_ERASESENDING ;
Eeprom32_state_after_erase = E32_WRITESTART ;
#endif
// }
// }
}
if ( Eeprom32_process_state == E32_WRITESTART )
{
uint32_t total_size ;
p = Eeprom32_source_address;
q = (uint8_t *) &Eeprom_buffer.data;
if (p != q) {
for (x = 0; x < Eeprom32_data_size; x += 1) {
*q++ = *p++; // Copy the data to temp buffer
}
}
Eeprom_buffer.header.sequence_no = ++File_system[Eeprom32_file_index].sequence_no;
File_system[Eeprom32_file_index].size = Eeprom_buffer.header.data_size = Eeprom32_data_size;
Eeprom_buffer.header.flags = 0;
Eeprom_buffer.header.hcsum = byte_checksum((uint8_t *) &Eeprom_buffer, 7);
total_size = Eeprom32_data_size + sizeof(struct t_eeprom_header);
eeAddress = Eeprom32_address; // Block start address
x = total_size / 256; // # sub blocks
x <<= 8; // to offset address
eeAddress += x; // Add it in
p = (uint8_t *) &Eeprom_buffer;
p += x; // Add offset
x = total_size % 256; // Size of last bit
if (x == 0) // Last bit empty
{
x = 256;
p -= x;
eeAddress -= x;
}
Eeprom32_buffer_address = p;
Eeprom32_address = eeAddress;
write32_eeprom_block(eeAddress, p, x, EE_NOWAIT);
Eeprom32_process_state = E32_WRITESENDING ;
}
if ( Eeprom32_process_state == E32_WRITESENDING )
{
if ( Spi_complete )
{
Eeprom32_process_state = E32_WRITEWAITING ;
}
}
if ( Eeprom32_process_state == E32_WRITEWAITING )
{
x = eeprom_read_status() ;
if ( ( x & 1 ) == 0 )
{
if ( ( Eeprom32_address & 0x0FFF ) != 0 ) // More to write
{
Eeprom32_address -= 256 ;
Eeprom32_buffer_address -= 256 ;
write32_eeprom_block( Eeprom32_address, Eeprom32_buffer_address, 256, EE_NOWAIT ) ;
Eeprom32_process_state = E32_WRITESENDING ;
}
else
{
File_system[Eeprom32_file_index].block_no ^= 1 ; // This is now the current block
#if 0
// now erase the other block
File_system[Eeprom32_file_index].block_no ^= 1 ; // This is now the current block
eeAddress = Eeprom32_address ^ 0x00001000 ; // Address of block to erase
eeprom_write_enable() ;
p = Spi_tx_buf ;
*p = 0x20 ; // Block Erase command
*(p+1) = eeAddress >> 16 ;
*(p+2) = eeAddress >> 8 ;
*(p+3) = eeAddress ; // 3 bytes address
spi_PDC_action( p, 0, 0, 4, 0 ) ;
Eeprom32_process_state = E32_ERASESENDING ;
Eeprom32_state_after_erase = E32_IDLE ;
#endif
Eeprom32_process_state = E32_IDLE ;
}
}
}
if ( Eeprom32_process_state == E32_ERASESENDING )
{
if ( Spi_complete )
{
Eeprom32_process_state = E32_ERASEWAITING ;
}
}
if ( Eeprom32_process_state == E32_ERASEWAITING )
{
x = eeprom_read_status() ;
if ( ( x & 1 ) == 0 )
{ // Command finished
Eeprom32_process_state = Eeprom32_state_after_erase ;
}
}
}
#if defined(SDCARD)
const pm_char * eeBackupModel(uint8_t i_fileSrc)
{
char *buf = reusableBuffer.modelsel.mainname;
FIL archiveFile;
DIR archiveFolder;
UINT written;
if (!sdMounted()) {
return STR_NO_SDCARD;
}
// check and create folder here
strcpy(buf, STR_MODELS_PATH);
FRESULT result = f_opendir(&archiveFolder, buf);
if (result != FR_OK) {
if (result == FR_NO_PATH)
result = f_mkdir(buf);
if (result != FR_OK)
return SDCARD_ERROR(result);
}
buf[sizeof(MODELS_PATH)-1] = '/';
strcpy(strcat_modelname(&buf[sizeof(MODELS_PATH)], i_fileSrc), STR_MODELS_EXT);
result = f_open(&archiveFile, buf, FA_CREATE_ALWAYS | FA_WRITE);
if (result != FR_OK) {
return SDCARD_ERROR(result);
}
strcpy(statusLineMsg, PSTR("File "));
strcpy(statusLineMsg+5, &buf[sizeof(MODELS_PATH)]);
uint16_t size = File_system[i_fileSrc+1].size;
*(uint32_t*)&buf[0] = O9X_FOURCC;
buf[4] = g_eeGeneral.version;
buf[5] = 'M';
*(uint16_t*)&buf[6] = size;
result = f_write(&archiveFile, buf, 8, &written);
if (result != FR_OK || written != 8) {
f_close(&archiveFile);
return SDCARD_ERROR(result);
}
read32_eeprom_data( (File_system[i_fileSrc+1].block_no << 12) + sizeof( struct t_eeprom_header), ( uint8_t *)&Eeprom_buffer.data.model_data, size) ;
result = f_write(&archiveFile, (uint8_t *)&Eeprom_buffer.data.model_data, size, &written);
f_close(&archiveFile);
if (result != FR_OK || written != size) {
return SDCARD_ERROR(result);
}
showStatusLine();
return NULL;
}
const pm_char * eeRestoreModel(uint8_t i_fileDst, char *model_name)
{
char *buf = reusableBuffer.modelsel.mainname;
FIL restoreFile;
UINT read;
if (!sdMounted()) {
return STR_NO_SDCARD;
}
strcpy(buf, STR_MODELS_PATH);
buf[sizeof(MODELS_PATH)-1] = '/';
strcpy(&buf[sizeof(MODELS_PATH)], model_name);
strcpy(&buf[strlen(buf)], STR_MODELS_EXT);
FRESULT result = f_open(&restoreFile, buf, FA_OPEN_EXISTING | FA_READ);
if (result != FR_OK) {
return SDCARD_ERROR(result);
}
if (f_size(&restoreFile) < 8) {
f_close(&restoreFile);
return STR_INCOMPATIBLE;
}
result = f_read(&restoreFile, (uint8_t *)buf, 8, &read);
if (result != FR_OK || read != 8) {
f_close(&restoreFile);
return SDCARD_ERROR(result);
}
if (*(uint32_t*)&buf[0] != O9X_FOURCC || (uint8_t)buf[4] != EEPROM_VER || buf[5] != 'M') {
f_close(&restoreFile);
return STR_INCOMPATIBLE;
}
uint16_t size = max((uint16_t)sizeof(g_model), *(uint16_t*)&buf[6]);
if (eeModelExists(i_fileDst)) {
eeDeleteModel(i_fileDst);
}
memset((uint8_t *)&Eeprom_buffer.data.model_data, 0, sizeof(g_model));
result = f_read(&restoreFile, ( uint8_t *)&Eeprom_buffer.data.model_data, size, &read);
f_close(&restoreFile);
if (result != FR_OK || read != read) {
return STR_INCOMPATIBLE;
}
// TODO flash saving ...
if (read > sizeof(g_model.header.name))
memcpy(modelHeaders[i_fileDst].name, Eeprom_buffer.data.model_data.header.name, sizeof(g_model.header.name));
else
memset(modelHeaders[i_fileDst].name, 0, sizeof(g_model.header.name));
Eeprom32_source_address = (uint8_t *)&Eeprom_buffer.data.model_data; // Get data from here
Eeprom32_data_size = sizeof(g_model); // This much
Eeprom32_file_index = i_fileDst + 1; // This file system entry
Eeprom32_process_state = E32_BLANKCHECK;
eeWaitFinished();
return NULL;
}
#endif