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:
parent
f4df52a033
commit
942e658c8e
707 changed files with 0 additions and 0 deletions
809
radio/src/eeprom_raw.cpp
Normal file
809
radio/src/eeprom_raw.cpp
Normal 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
|
Loading…
Add table
Add a link
Reference in a new issue