diff --git a/src/Makefile b/src/Makefile index 0b76a9784..1077a4465 100644 --- a/src/Makefile +++ b/src/Makefile @@ -80,7 +80,7 @@ DISPLAY_USER_DATA = NO PXX = NO # DSM2 (Spektrum) protocol -DSM2 = YES +DSM2 = NO # Silver protocol SILVER = NO @@ -178,8 +178,6 @@ CPPDEFS = -DF_CPU=$(F_CPU)UL # NOTE: PCB version now overrides all the earlier individual settings # These individual settings work only for PCB=STD -CPPDEFS += -DEEPROM_ASYNC_WRITE - ifeq ($(PCB), STD) # STD PCB, so ... diff --git a/src/drivers.cpp b/src/drivers.cpp index 3e6f669c7..46e1d429c 100644 --- a/src/drivers.cpp +++ b/src/drivers.cpp @@ -23,8 +23,6 @@ #ifndef SIMU -#ifdef EEPROM_ASYNC_WRITE - uint16_t eeprom_pointer; const char* eeprom_buffer_data; volatile int8_t eeprom_buffer_size = 0; @@ -77,50 +75,6 @@ void eeWriteBlockCmp(const void *i_pointer_ram, void *i_pointer_eeprom, size_t s } } -#else - -///opt/cross/avr/include/avr/eeprom.h -static inline void __attribute__ ((always_inline)) -eeprom_write_byte_cmp (uint8_t dat, uint16_t pointer_eeprom) -{ - //see /home/thus/work/avr/avrsdk4/avr-libc-1.4.4/libc/misc/eeprom.S:98 143 -#if defined (PCBV3) - while(EECR & (1<freeList ,sizeof(eeFs.freeList)); } + +static void EeFsFlushDirEnt(uint8_t i_fileId) +{ + eeWriteBlockCmp(&eeFs.files[i_fileId], &((EeFs*)0)->files[i_fileId], sizeof(DirEnt)); +} + static void EeFsFlush() { eeWriteBlockCmp(&eeFs, 0,sizeof(eeFs)); @@ -90,7 +104,6 @@ uint16_t EeFsGetFree() return ret; } -// #ifndef EEPROM_ASYNC_WRITE TODO because duplicate code static void EeFsFree(uint8_t blk){///free one or more blocks uint8_t i = blk; while( EeFsGetLink(i)) i = EeFsGetLink(i); @@ -98,25 +111,10 @@ static void EeFsFree(uint8_t blk){///free one or more blocks eeFs.freeList = blk; //chain in front EeFsFlushFreelist(); } -// #endif - -#ifndef EEPROM_ASYNC_WRITE -static uint8_t EeFsAlloc(){ ///alloc one block from freelist - uint8_t ret=eeFs.freeList; - if(ret){ - eeFs.freeList = EeFsGetLink(ret); - EeFsFlushFreelist(); - EeFsSetLink(ret,0); - } - return ret; -} -#endif int8_t EeFsck() { -#ifdef EEPROM_ASYNC_WRITE s_sync_write = true; -#endif uint8_t *bufp; static uint8_t buffer[BLOCKS]; @@ -129,45 +127,45 @@ int8_t EeFsck() uint8_t *startP = i==MAXFILES ? &eeFs.freeList : &eeFs.files[i].startBlk; uint8_t lastBlk = 0; blk = *startP; - while(blk){ - if( ( blk < FIRSTBLK ) //goto err_1; //bad blk index - || (blk >= BLOCKS ) //goto err_2; //bad blk index - || (bufp[blk] ))//goto err_3; //blk double usage + while (blk) { + if (blk < FIRSTBLK || // bad blk index + blk >= BLOCKS || // bad blk index + bufp[blk]) // blk double usage { - if(lastBlk){ - EeFsSetLink(lastBlk,0); - }else{ - *startP = 0; //interrupt chain at startpos + if (lastBlk) { + EeFsSetLink(lastBlk, 0); + } + else { + *startP = 0; // interrupt chain at startpos EeFsFlush(); } - blk=0; //abort - }else{ + blk = 0; // abort + } + else { bufp[blk] = i+1; lastBlk = blk; blk = EeFsGetLink(blk); } } } - for(blk = FIRSTBLK; blk < BLOCKS; blk++){ - if(bufp[blk]==0) { //goto err_4; //unused block - EeFsSetLink(blk,eeFs.freeList); - eeFs.freeList = blk; //chain in front + for (blk=FIRSTBLK; blk=(BS-1)){ - m_ofs=0; - if( ! EeFsGetLink(m_currBlk) ){ - EeFsSetLink(m_currBlk, EeFsAlloc()); - } - m_currBlk = EeFsGetLink(m_currBlk); - } - if(!m_currBlk) { - s_write_err = ERR_FULL; - break; - } - uint8_t l = BS-1-m_ofs; if(l>len) l=len; - EeFsSetDat(m_currBlk, m_ofs, buf, l); - buf +=l; - m_ofs +=l; - len -=l; - } - m_pos += i_len - len; - return i_len - len; -} - -#endif - - -#ifdef EEPROM_ASYNC_WRITE - void RlcFile::create(uint8_t i_fileId, uint8_t typ, uint8_t sync_write) { // all write operations will be executed on FILE_TMP @@ -468,6 +416,41 @@ void RlcFile::create(uint8_t i_fileId, uint8_t typ, uint8_t sync_write) s_sync_write = sync_write; } +/* + * Copy file src to dst + */ +bool RlcFile::copy(uint8_t i_fileDst, uint8_t i_fileSrc) +{ + EFile theFile2; + theFile2.openRd(i_fileSrc); + + create(i_fileDst, FILE_TYP_MODEL/*optimization, only model files are copied. should be eeFs.files[i_fileSrc].typ*/, true); + uint8_t buf[15]; + uint8_t len; + while ((len=theFile2.read(buf, 15))) + { + write(buf, len); + if (errno() != 0) { + s_sync_write = false; + return false; + } + } + + uint8_t fri=0; + if (m_currBlk && (fri=EeFsGetLink(m_currBlk))) + EeFsSetLink(m_currBlk, 0); + + eeFs.files[FILE_TMP].size = m_pos; + EFile::swap(m_fileId, FILE_TMP); + + if (fri) EeFsFree(fri); //chain in + + assert(!m_write_step); + + s_sync_write = false; + return true; +} + void RlcFile::writeRlc(uint8_t i_fileId, uint8_t typ, uint8_t*buf, uint16_t i_len, uint8_t sync_write) { create(i_fileId, typ, sync_write); @@ -541,7 +524,7 @@ void RlcFile::nextRlcWriteStep() case WRITE_START_STEP: { uint8_t fri=0; - eeFs.files[FILE_TMP].size = m_pos; + if (m_currBlk && ( fri = EeFsGetLink(m_currBlk))) { uint8_t prev_freeList = eeFs.freeList; eeFs.freeList = fri; @@ -552,9 +535,19 @@ void RlcFile::nextRlcWriteStep() } } - case WRITE_FLUSH_STEP: // TODO could be avoided - m_write_step = WRITE_SWAP_STEP; - EeFsFlush(); //chained out + case WRITE_FINAL_DIRENT_STEP: + m_currBlk = eeFs.files[FILE_TMP].startBlk; + eeFs.files[FILE_TMP].startBlk = eeFs.files[m_fileId].startBlk; + eeFs.files[m_fileId].startBlk = m_currBlk; + eeFs.files[m_fileId].size = m_pos; + eeFs.files[m_fileId].typ = eeFs.files[FILE_TMP].typ; + m_write_step = WRITE_TMP_DIRENT_STEP; + EeFsFlushDirEnt(m_fileId); + return; + + case WRITE_TMP_DIRENT_STEP: + m_write_step = 0; + EeFsFlushDirEnt(FILE_TMP); return; case WRITE_FREE_UNUSED_BLOCKS_STEP1: @@ -563,13 +556,9 @@ void RlcFile::nextRlcWriteStep() return; case WRITE_FREE_UNUSED_BLOCKS_STEP2: - m_write_step = WRITE_FLUSH_STEP; + m_write_step = WRITE_FINAL_DIRENT_STEP; EeFsFlushFreelist(); return; - - case WRITE_SWAP_STEP: - m_write_step = 0; - EFile::swap(m_fileId, FILE_TMP); } } @@ -585,103 +574,4 @@ void RlcFile::flush() s_sync_write = false; } -#else - -void RlcFile::create(uint8_t i_fileId, uint8_t typ, uint16_t maxTme10ms) -{ - openRlc(i_fileId); //internal use - eeFs.files[i_fileId].typ = typ; - eeFs.files[i_fileId].size = 0; - m_stopTime10ms = get_tmr10ms() + maxTme10ms; -} - -// G: Write runlength (RLE) compressed bytes -uint16_t RlcFile::writeRlc(uint8_t i_fileId, uint8_t typ,uint8_t*buf,uint16_t i_len, uint8_t maxTme10ms){ - - create(i_fileId,typ,maxTme10ms); - bool run0 = buf[0] == 0; - uint8_t cnt = 1; - uint8_t cnt0 = 0; - uint16_t i = 0; - if(i_len==0) goto close; - - //RLE compression: - //rb = read byte - //if (rb | 0x80) write rb & 0x7F zeros - //else write rb bytes - for( i=1; 1 ; i++) // !! laeuft ein byte zu weit !! - { - bool cur0 = buf[i] == 0; - if(cur0 != run0 || cnt==0x3f || (cnt0 && cnt==0xf)|| i==i_len){ - if(run0){ - assert(cnt0==0); - if(cnt<8 && i!=i_len) - cnt0 = cnt; //aufbew fuer spaeter - else { - if( write1(cnt|0x40)!=1) goto error;//-cnt&0x3f - } - }else{ - if(cnt0){ - if( write1(0x80 | (cnt0<<4) | cnt)!=1) goto error;//-cnt0xx-cnt - cnt0 = 0; - }else{ - if( write1(cnt) !=1) goto error;//-cnt - } - uint8_t ret=write(&buf[i-cnt],cnt); - if( ret !=cnt) { cnt-=ret; goto error;}//-cnt - } - cnt=0; - if(i==i_len) break; - run0 = cur0; - } - cnt++; - } - if(0){ - error: - i-=cnt+cnt0; -#ifdef SIMU - switch(s_write_err){ - default: - case ERR_NONE: - assert(!"missing errno"); - break; - case ERR_FULL: - printf("ERROR filesystem overflow! written: %d missing: %d\n",i,i_len-i); - break; - case ERR_TMO: - printf("ERROR filesystem write timeout %d 0ms\n",(int16_t)(m_stopTime10ms - g_tmr10ms)); - break; - } -#endif - } - close: - close(); - return i; -} - -#endif - -// G: Close file and truncate at this blk. Add any remaining blocks to freeList chain -void RlcFile::close() -{ - uint8_t fri=0; - - if(m_currBlk && ( fri = EeFsGetLink(m_currBlk))) EeFsSetLink(m_currBlk, 0); - -#ifdef EEPROM_ASYNC_WRITE - eeFs.files[FILE_TMP].size = m_pos; - EFile::swap(m_fileId, FILE_TMP); -#else - eeFs.files[m_fileId].size = m_pos; - EeFsFlush(); //chained out -#endif - - if(fri) EeFsFree( fri ); //chain in - -#ifdef EEPROM_ASYNC_WRITE - m_write_step = 0; - s_sync_write = false; -#endif -} - diff --git a/src/file.h b/src/file.h index 8d27dcdb7..82d0351ba 100644 --- a/src/file.h +++ b/src/file.h @@ -29,12 +29,15 @@ // bs=32 64 blocks verlust link: 64 16files:16*16 256 sum 320 // #if defined(PCBV3) -#define EESIZE 4096 -#define BS 32 +// 4096 - 16 bytes to give 255 blocks, since we can't address 256 block in an 8-bit register +#define EESIZE 4080 #else #define EESIZE 2048 -#define BS 16 #endif +#define BS 16 + +#define FILE_TYP_GENERAL 1 +#define FILE_TYP_MODEL 2 /// fileId of general file #define FILE_GENERAL 0 @@ -47,9 +50,7 @@ int8_t EeFsck(); void EeFsFormat(); uint16_t EeFsGetFree(); -#ifdef EEPROM_ASYNC_WRITE extern volatile int8_t eeprom_buffer_size; -#endif class EFile { @@ -82,9 +83,6 @@ class EFile #define ERR_NONE 0 #define ERR_FULL 1 -#ifndef EEPROM_ASYNC_WRITE -#define ERR_TMO 2 -#endif extern uint8_t s_write_err; // error reasons extern uint8_t s_sync_write; @@ -96,7 +94,6 @@ class RlcFile: public EFile uint8_t m_bRlc; // control byte for run length decoder uint8_t m_zeroes; -#ifdef EEPROM_ASYNC_WRITE uint8_t m_flags; #define WRITE_FIRST_LINK 0x01 #define WRITE_NEXT_LINK_1 0x02 @@ -104,8 +101,8 @@ class RlcFile: public EFile #define WRITE_START_STEP 0x10 #define WRITE_FREE_UNUSED_BLOCKS_STEP1 0x20 #define WRITE_FREE_UNUSED_BLOCKS_STEP2 0x30 -#define WRITE_FLUSH_STEP 0x40 -#define WRITE_SWAP_STEP 0x50 +#define WRITE_FINAL_DIRENT_STEP 0x40 +#define WRITE_TMP_DIRENT_STEP 0x50 uint8_t m_write_step; uint16_t m_rlc_len; @@ -114,17 +111,16 @@ class RlcFile: public EFile uint8_t m_write1_byte; uint8_t m_write_len; uint8_t * m_write_buf; -#else - uint16_t m_stopTime10ms; // maximum point of time for writing -#endif public: void openRlc(uint8_t i_fileId); - -#ifdef EEPROM_ASYNC_WRITE void create(uint8_t i_fileId, uint8_t typ, uint8_t sync_write); + + ///copy contents of i_fileSrc to i_fileDst + bool copy(uint8_t i_fileDst, uint8_t i_fileSrc); + inline bool isWriting() { return m_write_step != 0; } void write(uint8_t*buf, uint8_t i_len); void write1(uint8_t b); @@ -132,26 +128,6 @@ public: void nextRlcWriteStep(); void writeRlc(uint8_t i_fileId, uint8_t typ, uint8_t *buf, uint16_t i_len, uint8_t sync_write); void flush(); -#else - /// create a new file with given fileId, - /// !!! if this file already exists, then all blocks are reused - /// and all contents will be overwritten. - /// after writing close has to be called - - void create(uint8_t i_fileId, uint8_t typ, uint16_t maxTme10ms); - - uint8_t write(uint8_t*buf, uint8_t i_len); - uint8_t write1(uint8_t b); - ///open file, write to file and close it. - ///If file existed before, then contents is overwritten. - ///If file was larger before, then unused blocks are freed - uint16_t writeRlc(uint8_t i_fileId, uint8_t typ,uint8_t*buf,uint16_t i_len, uint8_t maxTme10ms); -#endif - - /* - * close file and truncate the blockchain if to long. - */ - void close(); ///read from opened file and decode rlc-coded data #ifdef TRANSLATIONS diff --git a/src/frsky.cpp b/src/frsky.cpp index a0575617d..e5214a165 100644 --- a/src/frsky.cpp +++ b/src/frsky.cpp @@ -20,6 +20,8 @@ #include "gruvin9x.h" #include "frsky.h" +#include "ff.h" // TODO +// #include // TODO // Enumerate FrSky packet codes #define LINKPKT 0xfe @@ -76,6 +78,23 @@ void frskyPushValue(uint8_t *&ptr, uint8_t value) } } +#ifdef DISPLAY_USER_DATA +/* + Copies all available bytes (up to max bufsize) from frskyUserData circular + buffer into supplied *buffer. Returns number of bytes copied (or zero) +*/ +uint8_t frskyGetUserData(char *buffer, uint8_t bufSize) +{ + uint8_t i = 0; + while (!frskyUserData.isEmpty()) + { + buffer[i] = frskyUserData.get(); + i++; + } + return i; +} +#endif + #ifdef FRSKY_HUB int8_t parseTelemHubIndex(uint8_t index) { @@ -133,7 +152,7 @@ void parseTelemHubByte(uint8_t byte) ((uint8_t*)&frskyHubData)[structPos+1] = byte; state = TS_IDLE; } -#endif +#endif /* Called from somewhere in the main loop or a low priority interrupt @@ -465,11 +484,102 @@ void FrskyData::set(uint8_t value) max = value; if (!min || min > value) min = value; - } +} + +// TODO not here! +#if defined (PCBV3) +char g_logFilename[21]; // "/G9XLOGS/M00_000.TXT\0" max required length = 21 +// These global so we can close any open file from anywhere +FATFS FATFS_Obj; +FIL g_oLogFile; +#endif void resetTelemetry() { memset(frskyTelemetry, 0, sizeof(frskyTelemetry)); memset(frskyRSSI, 0, sizeof(frskyRSSI)); + +#if defined (PCBV3) + + // Determine and set log file filename + + FRESULT result; + + // close any file left open. E.G. Changing models with log switch still on. + if (g_oLogFile.fs) f_close(&g_oLogFile); + + strcpy(g_logFilename, "/G9XLOGS/M00_000.TXT"); + + uint8_t num = g_eeGeneral.currModel + 1; + char *n = &g_logFilename[11]; + *n = (char)((num % 10) + '0'); + *(--n) = (char)((num / 10) + '0'); + + result = f_mount(0, &FATFS_Obj); + if (result!=FR_OK) + { + strcpy(g_logFilename, "FILE SYSTEM ERROR"); + } + else + { + // Skip over any existing log files ... _000, _001, etc. (or find first gap in numbering) + while (1) + { + result = f_open(&g_oLogFile, g_logFilename, FA_OPEN_EXISTING | FA_READ); + + if (result == FR_OK) + { + f_close(&g_oLogFile); + + // bump log file counter (file extension) + n = &g_logFilename[15]; + if (++*n > '9') + { + *n='0'; + n--; + if (++*n > '9') + { + *n='0'; + n--; + if (++*n > '9') + { + *n='0'; + break; // Wow. We looped back around past 999 to 000! abort loop + } + } + } + } + else if (result == FR_NO_PATH) + { + if (f_mkdir("/G9XLOGS") != FR_OK) + { + result = FR_NO_PATH; + break; + } + else + continue; + } + else + break; + } + + switch (result) + { + case FR_NO_PATH: + strcpy(g_logFilename, "Check /G9XLOGS folder"); + break; + case FR_NOT_READY: + strcpy(g_logFilename, "DATA CARD NOT PRESENT"); + break; + + default: + break; + } + } + + // g_logFilename should now be set appropriately. + +#endif + } diff --git a/src/general_menus.cpp b/src/general_menus.cpp index c699fee3c..faac57c30 100644 --- a/src/general_menus.cpp +++ b/src/general_menus.cpp @@ -451,6 +451,14 @@ void menuProcDiagKeys(uint8_t event) lcd_putcAtt(5*FW+2, y, t+'0', t); } +#if defined (PCBV4) + for(uint8_t i=0; i<2; i++) { + uint8_t y = i*FH + FH; + lcd_putsn_P(14*FW, y, PSTR("RE1RE2")+3*i, 3); + lcd_outdezNAtt(18*FW, y, g_rotenc[i], LEFT|(keyState((EnumKeys)(SW_RE1+i)) ? INVERS : 0)); + } +#endif + lcd_putsn_P(14*FW, 3*FH, PSTR("Trim- +"), 7); for(uint8_t i=0; i<4; i++) { @@ -474,8 +482,10 @@ void menuProcDiagAna(uint8_t event) uint8_t y=i*FH; lcd_putsn_P( 4*FW, y,PSTR("A1A2A3A4A5A6A7A8")+2*i,2); lcd_outhex4( 8*FW, y,anaIn(i)); - if(i<7) lcd_outdez8(17*FW, y, (int32_t)calibratedStick[i]*100/1024); - if(i==7) putsVolts(17*FW, y, g_vbat100mV, (sub==1 ? INVERS : 0)); + if(i<7) + lcd_outdez8(17*FW, y, (int32_t)calibratedStick[i]*100/1024); + else + putsVolts(17*FW, y, g_vbat100mV, (sub==1 ? INVERS : 0)); } // lcd_outdezAtt( 21*FW, 3*FH, g_eeGeneral.vBatCalib, 0) ; // lcd_outdezAtt( 21*FW, 4*FH, abRunningAvg, 0) ; diff --git a/src/gruvin9x.cpp b/src/gruvin9x.cpp index a70388ee4..8efbc93e5 100644 --- a/src/gruvin9x.cpp +++ b/src/gruvin9x.cpp @@ -43,8 +43,8 @@ mode4 ail thr ele rud EEGeneral g_eeGeneral; ModelData g_model; -uint16_t g_tmr1Latency_max; -uint16_t g_tmr1Latency_min = 0x7ff; +uint8_t g_tmr1Latency_max; +uint8_t g_tmr1Latency_min; uint16_t g_timeMain; uint16_t g_time_per10; @@ -256,12 +256,13 @@ int16_t Expo::expo(int16_t x) #endif -void applyExpos(int16_t *anas) +void applyExpos(int16_t *anas, uint8_t phase) { static int16_t anas2[4]; // values before expo, to ensure same expo base when multiple expo lines are used memcpy(anas2, anas, sizeof(anas2)); - uint8_t phase = getFlightPhase(); + if (phase == 255) + phase = getFlightPhase(); int8_t cur_chn = -1; for (uint8_t i=0; i=0 && k<8) { // && (event & _MSK_KEY_REPT)) //LH_DWN LH_UP LV_DWN LV_UP RV_DWN RV_UP RH_DWN RH_UP uint8_t idx = k/2; - uint8_t phase = getTrimFlightPhase(idx); + uint8_t phase = getTrimFlightPhase(idx, getFlightPhase()); int16_t before = getTrimValue(phase, idx); int8_t v = (s==0) ? min(32, abs(before)/4+1) : 1 << (s-1); // 1=>1 2=>2 3=>4 4=>8 bool thro = (((2-(g_eeGeneral.stickMode&1)) == idx) && g_model.thrTrim); @@ -817,7 +816,7 @@ void getADC_bandgap() { #if defined(PCBSTD) ADMUX=0x1E|ADC_VREF_TYPE; // Switch MUX to internal 1.22V reference - _delay_us(5); // short delay to stablise reference voltage + _delay_us(5); // short delay to stabilise reference voltage ADCSRA|=0x40; while ((ADCSRA & 0x10)==0); ADCSRA|=0x10; // grab a sample @@ -1093,13 +1092,13 @@ int32_t act [MAX_MIXERS] = {0}; uint8_t swOn [MAX_MIXERS] = {0}; uint8_t mixWarning; -inline void evalTrims() +inline void evalTrims(uint8_t phase) { for (uint8_t i=0; i throttle trim if applicable int16_t v = anas[i]; int32_t vv = 2*RESX; - int16_t trim = getTrimValue(getTrimFlightPhase(i), i); + int16_t trim = getTrimValue(getTrimFlightPhase(i, phase), i); if (IS_THROTTLE(i) && g_model.thrTrim) { if (g_eeGeneral.throttleReversed) trim = -trim; @@ -1113,7 +1112,7 @@ inline void evalTrims() } } -uint8_t evalSticks() +uint8_t evalSticks(uint8_t phase) { #ifdef HELI uint16_t d = 0; @@ -1178,10 +1177,10 @@ uint8_t evalSticks() } /* EXPOs */ - applyExpos(anas); + applyExpos(anas, phase); /* TRIMs */ - evalTrims(); + evalTrims(phase); return anaCenter; } @@ -1204,10 +1203,9 @@ void evalFunctions() } } -void perOut(int16_t *chanOut) +void perOut(int16_t *chanOut, uint8_t phase) { - uint8_t phase = getFlightPhase(); - uint8_t anaCenter = evalSticks(); + uint8_t anaCenter = evalSticks(phase); //===========BEEP CENTER================ anaCenter &= g_model.beepANACenter; @@ -1348,10 +1346,6 @@ void perOut(int16_t *chanOut) { #define DEL_MULT 256 - //if(init) { - //act[i]=(int32_t)v*DEL_MULT; - //swTog = false; - //} int16_t diff = v-act[i]/DEL_MULT; if(swTog) { @@ -1472,53 +1466,113 @@ void perOut(int16_t *chanOut) } } +#ifdef DISPLAY_USER_DATA +char userDataDisplayBuf[TELEM_SCREEN_BUFFER_SIZE]; +#endif + void perMain() { static uint16_t lastTMR; tick10ms = (get_tmr10ms() != lastTMR); lastTMR = get_tmr10ms(); - int16_t last_chans512[NUM_CHNOUT]; - int16_t next_chans512[NUM_CHNOUT]; - - static uint8_t last_phase = 0; +#define MAX_ACT 0xffff + static uint16_t fp_act[MAX_PHASES] = {0}; + static uint8_t s_fade_flight_phases = 0; + static uint8_t s_last_phase = 255; uint8_t phase = getFlightPhase(); - static uint8_t fading_out_timer = 0; - if (last_phase != phase) { - fading_out_timer = 10 * max(g_model.phaseData[last_phase].fadeOut, g_model.phaseData[phase].fadeIn); - last_phase = phase; + if (s_last_phase != phase) { + if (s_last_phase == 255) { + fp_act[phase] = MAX_ACT; } + else { + if (g_model.phaseData[s_last_phase].fadeOut) { + s_fade_flight_phases |= (1<%d\n", p, fp_act[p], next_chans512[2]); + for (uint8_t i=0; i delta) + fp_act[p] += delta; + else { + fp_act[p] = MAX_ACT; + s_fade_flight_phases -= (1< delta) + fp_act[p] -= delta; + else { + fp_act[p] = 0; + s_fade_flight_phases -= (1< 0) trimsCheckTimer -= 1; -#ifndef EEPROM_ASYNC_WRITE - eeCheck(); -#endif - +#if defined (FRSKY) + +/***** TEST CODE - Fr-Sky SD/MMC card / User Data experiments *****/ + +#if defined (PCBV3) + + /* Use light switch (on) to open telemtry test log file */ + static FRESULT result; + + static int8_t testLogOpen = 0; + + if(getSwitch(g_eeGeneral.lightSw,0)) + { + // while(1); // Test WDT + if ((testLogOpen==0) // if we know we haven't started logging ... + || ((testLogOpen==1) && !g_oLogFile.fs)) // ... or we thought we had, but the file got closed + { + result = f_mount(0, &FATFS_Obj); + if (result!=FR_OK) + { + testLogOpen = -1; + beepAgain = result - 1; + beepKey(); + } + else + { + // create new log file using filename set up in pers.cpp::resetTelemetry() + result = f_open(&g_oLogFile, g_logFilename, FA_OPEN_ALWAYS | FA_WRITE); + if (result!=FR_OK) + { + testLogOpen = -2; + beepAgain = result - 1; + beepKey(); + } + else + { + f_lseek(&g_oLogFile, g_oLogFile.fsize); // append + + testLogOpen = 1; + beepWarn2(); + } + } + } + } + else + { + if (testLogOpen==1) + { + f_close(&g_oLogFile); + beepWarn2(); + } + testLogOpen = 0; + } + + +#ifdef DISPLAY_USER_DATA + //////////////// + // Write raw user data into on-screen display line buffer + + char userDataRxBuffer[21]; // Temp buffer used to collect fr-sky user data + + // retrieve bytes from user data buffer and insert into display string, + // scrolling at the 21 character mark (edge of screen) + uint8_t numbytes = frskyGetUserData(userDataRxBuffer, 21); // Get as many bytes as we can + + static uint8_t displayBufferIndex; + for (uint8_t byt=0; byt < numbytes; byt++) + { + displayBufferIndex++; + if (displayBufferIndex > 20) + { + for (int xx=0; xx<20; xx++) // scroll one char left + userDataDisplayBuf[xx] = userDataDisplayBuf[xx+1]; + displayBufferIndex = 20; + } + userDataDisplayBuf[displayBufferIndex] = userDataRxBuffer[byt]; + + // Write the raw byte out to log file, if open + if (testLogOpen && (g_oLogFile.fs != 0)) + f_putc(userDataRxBuffer[byt], &g_oLogFile); + + } + //////////////// +#endif + +/***** END TEST CODE - Fr-Sky User Data experiments *****/ + +// PCBV3 +#endif +// FRSKY +#endif + lcd_clear(); uint8_t evt=getEvent(); evt = checkTrim(evt); @@ -1950,22 +2092,23 @@ uint16_t DEBUG2 = 0; void instantTrim() { + uint8_t phase = getFlightPhase(); + for (uint8_t i=0; i trim=%d\n", i, anas[i], i, trims[i], g_model.phaseData[phase].trim[i], g_model.subtrim[i], trim); if (trim < TRIM_EXTENDED_MIN) { trim = TRIM_EXTENDED_MIN; } if (trim > TRIM_EXTENDED_MAX) { trim = TRIM_EXTENDED_MAX; } - setTrimValue(phase, i, trim); + setTrimValue(trim_phase, i, trim); } } @@ -1978,7 +2121,7 @@ void moveTrimsToOffsets() // copy state of 3 primary to subtrim int16_t zero_chans512[NUM_CHNOUT]; s_noStickInputs = true; - perOut(zero_chans512); // do output loop - zero input sticks + perOut(zero_chans512, getFlightPhase()); // do output loop - zero input sticks s_noStickInputs = false; for (uint8_t i=0; i #if defined(PCBV3) +#include "ff.h" #include "time.h" #endif @@ -291,7 +292,9 @@ enum EnumKeys { SW_ID2 , SW_AileDR , SW_Gear , - SW_Trainer + SW_Trainer, + SW_RE1, + SW_RE2 }; #define CURVE_BASE 7 @@ -451,10 +454,6 @@ void per10ms(); /// Erzeugt periodisch alle Outputs ausser Bildschirmausgaben. void zeroVariables(); -#define NO_TRAINER 0x01 -#define NO_INPUT 0x02 -extern void perOut(int16_t *chanOut, uint8_t att); - /// Liefert den Zustand des Switches 'swtch'. Die Numerierung erfolgt ab 1 /// (1=SW_ON, 2=SW_ThrCt, 10=SW_Trainer). 0 Bedeutet not conected. /// Negative Werte erzeugen invertierte Ergebnisse. @@ -474,7 +473,7 @@ bool getSwitch(int8_t swtch, bool nc); /// uint8_t getFlightPhase(); -uint8_t getTrimFlightPhase(uint8_t idx, int8_t phase=-1); +uint8_t getTrimFlightPhase(uint8_t idx, uint8_t phase); extern int16_t getTrimValue(uint8_t phase, uint8_t idx); extern void setTrimValue(uint8_t phase, uint8_t idx, int16_t trim); @@ -498,8 +497,8 @@ extern uint8_t Timer2_running ; extern uint16_t timer2 ; void resetTimer2() ; -extern uint16_t g_tmr1Latency_max; -extern uint16_t g_tmr1Latency_min; +extern uint8_t g_tmr1Latency_max; +extern uint8_t g_tmr1Latency_min; extern uint16_t g_timeMain; extern uint16_t g_time_per10; @@ -560,15 +559,13 @@ template inline t limit(t mi, t x, t ma){ return min(max(mi,x),ma); } /// eeCheck ins EEPROM zurueckgeschrieben. void eeWriteBlockCmp(const void *i_pointer_ram, void *i_pointer_eeprom, size_t size); void eeDirty(uint8_t msk); -#ifdef EEPROM_ASYNC_WRITE inline void eeFlush() { theFile.flush(); } -#endif void eeCheck(bool immediately=false); void eeReadAll(); bool eeModelExists(uint8_t id); uint16_t eeLoadModelName(uint8_t id, char *name); void eeLoadModel(uint8_t id); -int8_t eeDuplicateModel(uint8_t id, bool down=true); +int8_t eeFindEmptyModel(uint8_t id, bool down); ///number of real input channels (1-9) plus virtual input channels X1-X4 #define NUM_XCHNRAW (NUM_STICKS+NUM_POTS+2/*MAX/FULL*/+3/*CYC1-CYC3*/+NUM_PPM+NUM_CHNOUT+NUM_TELEMETRY) @@ -651,7 +648,7 @@ extern uint16_t expou(uint16_t x, uint16_t k); extern int16_t expo(int16_t x, int16_t k); extern int16_t intpol(int16_t, uint8_t); extern int16_t applyCurve(int16_t, uint8_t, uint8_t srcRaw); -extern void applyExpos(int16_t *anas); +extern void applyExpos(int16_t *anas, uint8_t phase=255); extern uint16_t anaIn(uint8_t chan); extern int16_t calibratedStick[7]; @@ -729,11 +726,21 @@ inline bool isFunctionActive(uint8_t func) return active_functions & (1 << (func-1)); } +#ifdef DISPLAY_USER_DATA +#define TELEM_SCREEN_BUFFER_SIZE 21 +extern char userDataDisplayBuf[TELEM_SCREEN_BUFFER_SIZE]; // text buffer for frsky telem. user data experiments +#endif + #if defined (PCBV3) extern char g_logFilename[21]; // pers.cpp::resetTelemetry() extern FATFS FATFS_Obj; // pers.cpp::resetTelemetry() extern FIL g_oLogFile; // pers.cpp::resetTelemetry() #endif +#if defined (PCBV4) +// Global rotary encoder registers -- 8-bit, 0-255 +extern volatile uint8_t g_rotenc[2]; +#endif + #endif // gruvin9x_h /*eof*/ diff --git a/src/gtests.cpp b/src/gtests.cpp index 744666994..cc4614560 100644 --- a/src/gtests.cpp +++ b/src/gtests.cpp @@ -140,7 +140,7 @@ TEST(EEPROM, eeCheckImmediately) { EXPECT_EQ(sz, 300); } -TEST(EEPROM, eeDuplicateModel) { +TEST(EEPROM, copy) { eepromFile = NULL; // in memory uint8_t buf[1000]; @@ -151,7 +151,7 @@ TEST(EEPROM, eeDuplicateModel) { theFile.writeRlc(5, 6, buf, 300, true); - eeDuplicateModel(4); + theFile.copy(6, 5); theFile.openRd(6); uint16_t sz=0; @@ -250,6 +250,13 @@ TEST(getSwitch, circularCSW) { EXPECT_EQ(getSwitch(-(1+MAX_SWITCH-NUM_CSW), 0), true); } +TEST(getSwitch, nullSW) { + memset(&g_model, 0, sizeof(g_model)); + EXPECT_EQ(getSwitch(0, 0), false); + EXPECT_EQ(getSwitch(0, true), true); + EXPECT_EQ(getSwitch(0, 0), false); +} + int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/src/lcd.cpp b/src/lcd.cpp index 80b8f319c..a014a97a9 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -451,7 +451,7 @@ void putsFlightPhase(uint8_t x, uint8_t y, int8_t idx, uint8_t att) { if (idx==0) { lcd_putsAtt(x,y,PSTR("---"),att); return; } if (idx < 0) { lcd_vlineStip(x-2, y, 8, 0x5E/*'!'*/); idx = -idx; } - putsStrIdx(x, y, PSTR("FP"), idx, att); + putsStrIdx(x, y, PSTR("FP"), idx-1, att); } #define CURV_STR "---x>0x<0|x|f>0f<0|f|" diff --git a/src/model_menus.cpp b/src/model_menus.cpp index a9ff26df3..cecb235f4 100644 --- a/src/model_menus.cpp +++ b/src/model_menus.cpp @@ -148,10 +148,8 @@ void menuProcModelSelect(uint8_t event) TITLE("MODELSEL"); -#ifdef EEPROM_ASYNC_WRITE - // flush eeprom write - eeFlush(); -#endif + // flush eeprom write + eeFlush(); if (s_confirmation) { EFile::rm(FILE_MODEL(m_posVert)); // delete file @@ -180,7 +178,7 @@ void menuProcModelSelect(uint8_t event) { case EVT_ENTRY: m_posVert = sub = g_eeGeneral.currModel; - s_copyMode = 0; + s_copyMode = 0; // TODO only this one? s_copyTgtOfs = 0; s_copySrcRow = -1; break; @@ -192,68 +190,58 @@ void menuProcModelSelect(uint8_t event) } // no break case EVT_KEY_BREAK(KEY_EXIT): - if (s_copyTgtOfs || s_copySrcRow >= 0) { - eeCheck(true); // force writing of current model data before this is changed - do { - if (s_copyTgtOfs < 0) { - s_copyTgtOfs++; - m_posVert = (MAX_MODELS+m_posVert-1) % MAX_MODELS; - } - else { - s_copyTgtOfs--; - m_posVert = (m_posVert+1) % MAX_MODELS; - } -#ifdef EEPROM_ASYNC_WRITE - s_sync_write = true; -#endif - EFile::swap(FILE_MODEL(sub), FILE_MODEL(m_posVert)); -#ifdef EEPROM_ASYNC_WRITE - s_sync_write = false; -#endif - if (m_posVert == g_eeGeneral.currModel) { - g_eeGeneral.currModel = sub; - STORE_GENERALVARS; - } - else if (sub == g_eeGeneral.currModel) { - g_eeGeneral.currModel = m_posVert; - STORE_GENERALVARS; - } - sub = m_posVert; - } while (s_copyTgtOfs != 0); - - if (s_copySrcRow >= 0) { - EFile::rm(FILE_MODEL(sub)); - sub = m_posVert = s_copySrcRow; - s_copySrcRow = -1; - } + if (s_copyMode) { + sub = m_posVert = (s_copyMode == MOVE_MODE || s_copySrcRow<0) ? (16+sub+s_copyTgtOfs) % 16 : s_copySrcRow; // TODO reset s_copySrcRow? + s_copyMode = 0; // TODO only this one? + s_copySrcRow = -1; + s_copyTgtOfs = 0; + killEvents(_event); } - s_copyMode = 0; - killEvents(_event); - break; - case EVT_KEY_BREAK(KEY_MENU): - if (s_copyTgtOfs || s_copySrcRow >= 0) { - s_copyMode = 0; - } - else if (EFile::exists(FILE_MODEL(sub))) { - s_copyMode = (s_copyMode == COPY_MODE ? MOVE_MODE : COPY_MODE); - } - s_copySrcRow = -1; - s_copyTgtOfs = 0; break; case EVT_KEY_LONG(KEY_MENU): - if (s_copyTgtOfs) { + case EVT_KEY_BREAK(KEY_MENU): + if (s_copyMode && (s_copyTgtOfs || s_copySrcRow>=0)) { + eeCheck(true); // force writing of current model data before this is changed + + uint8_t cur = (16 + sub + s_copyTgtOfs) % 16; + + if (s_copyMode == COPY_MODE) { + if (!theFile.copy(FILE_MODEL(cur), FILE_MODEL(s_copySrcRow))) + cur = sub; + } + + s_copySrcRow = g_eeGeneral.currModel; // to update the currModel value + while (sub != cur) { + uint8_t src = cur; + cur = (s_copyTgtOfs > 0 ? cur+15 : cur+1) % 16; + EFile::swap(FILE_MODEL(src), FILE_MODEL(cur)); + if (src == s_copySrcRow) + s_copySrcRow = cur; + else if (cur == s_copySrcRow) + s_copySrcRow = src; + } + + if (s_copySrcRow != g_eeGeneral.currModel) { + g_eeGeneral.currModel = s_copySrcRow; + STORE_GENERALVARS; + } + + s_copyMode = 0; // TODO only this one? + s_copySrcRow = -1; s_copyTgtOfs = 0; - s_copyMode = 0; } - else { + else if (_event == EVT_KEY_LONG(KEY_MENU)) { eeCheck(true); // force writing of current model data before this is changed if (g_eeGeneral.currModel != sub) { g_eeGeneral.currModel = sub; STORE_GENERALVARS; + eeLoadModel(sub); } - eeLoadModel(sub); + killEvents(event); + } + else if (EFile::exists(FILE_MODEL(sub))) { + s_copyMode = (s_copyMode == COPY_MODE ? MOVE_MODE : COPY_MODE); } - killEvents(_event); break; case EVT_KEY_FIRST(KEY_LEFT): case EVT_KEY_FIRST(KEY_RIGHT): @@ -266,41 +254,25 @@ void menuProcModelSelect(uint8_t event) case EVT_KEY_FIRST(KEY_UP): case EVT_KEY_FIRST(KEY_DOWN): if (s_copyMode) { - eeCheck(true); int8_t next_ofs = (_event == EVT_KEY_FIRST(KEY_UP) ? s_copyTgtOfs+1 : s_copyTgtOfs-1); + if (next_ofs == 16 || next_ofs == -16) + next_ofs = 0; + if (s_copySrcRow < 0 && s_copyMode==COPY_MODE) { s_copySrcRow = oldSub; - // insert a model (in the first empty slot above / below) - m_posVert = eeDuplicateModel(s_copySrcRow, _event==EVT_KEY_FIRST(KEY_DOWN)); + // find a hole (in the first empty slot above / below) + m_posVert = eeFindEmptyModel(s_copySrcRow, _event==EVT_KEY_FIRST(KEY_DOWN)); if (m_posVert == (uint8_t)-1) { // no free room for duplicating the model beepWarn(); m_posVert = oldSub; - s_copyMode = 0; + s_copyMode = 0; // TODO only this one? s_copyTgtOfs = 0; s_copySrcRow = -1; } next_ofs = 0; sub = m_posVert; } - else { - // only swap the model with its neighbor -#ifdef EEPROM_ASYNC_WRITE - s_sync_write = true; -#endif - EFile::swap(FILE_MODEL(oldSub), FILE_MODEL(sub)); -#ifdef EEPROM_ASYNC_WRITE - s_sync_write = false; -#endif - if (oldSub == g_eeGeneral.currModel) { - g_eeGeneral.currModel = sub; - STORE_GENERALVARS; - } - else if (sub == g_eeGeneral.currModel) { - g_eeGeneral.currModel = oldSub; - STORE_GENERALVARS; - } - } s_copyTgtOfs = next_ofs; } break; @@ -308,21 +280,42 @@ void menuProcModelSelect(uint8_t event) if (sub-s_pgOfs < 1) s_pgOfs = max(0, sub-1); else if (sub-s_pgOfs > 5) s_pgOfs = min(MAX_MODELS-7, sub-4); + + // printf("copy_mode=%d s_copySrcRow=%d s_copyTgtOfs=%d sub=%d\n", s_copyMode, s_copySrcRow, s_copyTgtOfs, sub); fflush(stdout); + for (uint8_t i=0; i<7; i++) { uint8_t y=(i+1)*FH; uint8_t k=i+s_pgOfs; lcd_outdezNAtt(3*FW+2, y, k+1, LEADING0+((!s_copyMode && sub==k) ? INVERS : 0), 2); + + if (s_copyMode == MOVE_MODE || (s_copyMode == COPY_MODE && s_copySrcRow >= 0)) { + if (k == sub) { + if (s_copyMode == COPY_MODE) { + k = s_copySrcRow; + lcd_putc(20*FW+2, y, '+'); + } + else { + k = sub + s_copyTgtOfs; + } + } + else if (s_copyTgtOfs < 0 && ((k < sub && k >= sub+s_copyTgtOfs) || (k-16 < sub && k-16 >= sub+s_copyTgtOfs))) + k += 1; + else if (s_copyTgtOfs > 0 && ((k > sub && k <= sub+s_copyTgtOfs) || (k+16 > sub && k+16 <= sub+s_copyTgtOfs))) + k += 15; + } + + k %= 16; + if (EFile::exists(FILE_MODEL(k))) { uint16_t size = eeLoadModelName(k, name); putsModelName(4*FW, y, name, k, 0); lcd_outdezAtt(20*FW, y, size, 0); + if (k==g_eeGeneral.currModel && (s_copySrcRow<0 || i+s_pgOfs!=sub)) lcd_putc(1, y, '*'); } - if (k==g_eeGeneral.currModel) lcd_putc(1, y, '*'); - if (s_copyMode && k==sub) { - if (s_copyMode == COPY_MODE) - lcd_putc(20*FW+2, y, '+'); - lcd_rect(8, y-1, DISPLAY_W-1-7, 9, s_copyMode == COPY_MODE ? 0xff : 0x55); + + if (s_copyMode && sub==i+s_pgOfs) { lcd_filled_rect(9, y, DISPLAY_W-1-9, 7); + lcd_rect(8, y-1, DISPLAY_W-1-7, 9, s_copyMode == COPY_MODE ? 0xff : 0x55); } } diff --git a/src/pers.cpp b/src/pers.cpp index c8896c6d1..42364f7db 100644 --- a/src/pers.cpp +++ b/src/pers.cpp @@ -29,9 +29,6 @@ RlcFile theFile; //used for any file operation -#define FILE_TYP_GENERAL 1 -#define FILE_TYP_MODEL 2 - void generalDefault() { memset(&g_eeGeneral,0,sizeof(g_eeGeneral)); @@ -49,9 +46,7 @@ void generalDefault() g_eeGeneral.calibSpanNeg[i] = 0x180; g_eeGeneral.calibSpanPos[i] = 0x180; } - int16_t sum=0; - for(int i=0; i<12;i++) sum+=g_eeGeneral.calibMid[i]; - g_eeGeneral.chkSum = sum; + g_eeGeneral.chkSum = (0x200 * 7) + (0x180 * 5); } #ifdef TRANSLATIONS @@ -287,6 +282,13 @@ void eeLoadModel(uint8_t id) theFile.openRlc(FILE_MODEL(id)); uint16_t sz = theFile.readRlc((uint8_t*)&g_model, sizeof(g_model)); +#ifdef SIMU + if (sz > 0 && sz != sizeof(g_model)) { + printf("Model data read=%d bytes vs %d bytes\n", sz, sizeof(ModelData)); + fflush(stdout); + } +#endif + if (sz != sizeof(ModelData)) { // alert("Error Loading Model"); modelDefault(id); @@ -302,7 +304,7 @@ void eeLoadModel(uint8_t id) } } -int8_t eeDuplicateModel(uint8_t id, bool down) +int8_t eeFindEmptyModel(uint8_t id, bool down) { int8_t i = id; for (;;) { @@ -310,25 +312,6 @@ int8_t eeDuplicateModel(uint8_t id, bool down) if (!EFile::exists(FILE_MODEL(i))) break; if (i == id) return -1; // no free space in directory left } - - EFile theFile2; - theFile2.openRd(FILE_MODEL(id)); - -#ifdef EEPROM_ASYNC_WRITE - theFile.create(FILE_MODEL(i), FILE_TYP_MODEL, true); -#else - theFile.create(FILE_MODEL(i), FILE_TYP_MODEL, 600); -#endif - uint8_t buf[15]; - uint8_t len; - while((len=theFile2.read(buf, 15))) - { - theFile.write(buf, len); - if (errno() != 0) { - return false; - } - } - theFile.close(); return i; } @@ -346,20 +329,11 @@ void eeReadAll() generalDefault(); //alert(PSTR("default ok")); -#ifdef EEPROM_ASYNC_WRITE theFile.writeRlc(FILE_GENERAL, FILE_TYP_GENERAL,(uint8_t*)&g_eeGeneral,sizeof(EEGeneral), true); -#else - uint16_t sz = theFile.writeRlc(FILE_GENERAL,FILE_TYP_GENERAL,(uint8_t*)&g_eeGeneral,sizeof(EEGeneral), 200); - if(sz!=sizeof(EEGeneral)) alert(PSTR("genwrite error")); -#endif modelDefault(0); //alert(PSTR("modef ok")); -#ifdef EEPROM_ASYNC_WRITE theFile.writeRlc(FILE_MODEL(0), FILE_TYP_MODEL, (uint8_t*)&g_model, sizeof(g_model), true); -#else - theFile.writeRlc(FILE_MODEL(0), FILE_TYP_MODEL, (uint8_t*)&g_model, sizeof(g_model),200); -#endif //alert(PSTR("modwrite ok")); } @@ -368,22 +342,13 @@ void eeReadAll() uint8_t s_eeDirtyMsk; -#ifndef EEPROM_ASYNC_WRITE -static uint16_t s_eeDirtyTime10ms; -#define WRITE_DELAY_10MS 100 -#endif void eeDirty(uint8_t msk) { s_eeDirtyMsk |= msk; -#ifndef EEPROM_ASYNC_WRITE - if (msk) - s_eeDirtyTime10ms = get_tmr10ms(); -#endif } void eeCheck(bool immediately) { -#ifdef EEPROM_ASYNC_WRITE if (immediately) { eeFlush(); } @@ -396,41 +361,4 @@ void eeCheck(bool immediately) s_eeDirtyMsk = 0; theFile.writeRlc(FILE_MODEL(g_eeGeneral.currModel), FILE_TYP_MODEL, (uint8_t*)&g_model, sizeof(g_model), immediately); } -#else - uint8_t msk = s_eeDirtyMsk; - if (!msk) return; - if( !immediately && ((get_tmr10ms() - s_eeDirtyTime10ms) < WRITE_DELAY_10MS)) return; - s_eeDirtyMsk = 0; - - if(msk & EE_GENERAL){ - if(theFile.writeRlc(FILE_TMP, FILE_TYP_GENERAL, (uint8_t*)&g_eeGeneral, - sizeof(EEGeneral),20) == sizeof(EEGeneral)) - { - EFile::swap(FILE_GENERAL,FILE_TMP); - }else{ - if(errno()==ERR_TMO){ - s_eeDirtyMsk |= EE_GENERAL; //try again - s_eeDirtyTime10ms = get_tmr10ms() - WRITE_DELAY_10MS; - }else{ - alert(PSTR("EEPROM overflow")); - } - } - //first finish GENERAL, then MODEL !!avoid Toggle effect - } - if(msk & EE_MODEL){ - if(theFile.writeRlc(FILE_TMP, FILE_TYP_MODEL, (uint8_t*)&g_model, - sizeof(g_model),20) == sizeof(g_model)) - { - EFile::swap(FILE_MODEL(g_eeGeneral.currModel),FILE_TMP); - }else{ - if(errno()==ERR_TMO){ - s_eeDirtyMsk |= EE_MODEL; //try again - s_eeDirtyTime10ms = get_tmr10ms() - WRITE_DELAY_10MS; - }else{ - alert(PSTR("EEPROM overflow")); - } - } - } - //beepWarn1(); -#endif }