From ac45e5bfac4100207f540723fd69cd5000a972d0 Mon Sep 17 00:00:00 2001 From: bsongis Date: Sat, 8 Oct 2011 08:28:43 +0000 Subject: [PATCH] Just before reverting ... --- src/Makefile | 33 ++-- src/file.cpp | 8 + src/gruvin9x.cpp | 38 ++--- src/gruvin9x.h | 4 +- src/main_views.cpp | 7 +- src/model_menus.cpp | 358 ++++++++++++++++++++++++-------------------- src/myeeprom.h | 2 +- src/pers.cpp | 26 +++- 8 files changed, 266 insertions(+), 210 deletions(-) diff --git a/src/Makefile b/src/Makefile index d0776f561..0ab74f6ef 100644 --- a/src/Makefile +++ b/src/Makefile @@ -38,7 +38,7 @@ PCB = V4 # For this option you need to modify your hardware! # More information at [insertURLhere] # Values = STD, JETI, FRSKY -EXT = FRSKY +EXT = STD # Enable heli menu # Values = YES, NO @@ -50,11 +50,12 @@ TEMPLATES = YES # gruvin: BEEPER. Values = BUZZER, BUZZER_MOD or SPEAKER # (without a mod, BUZZER can make PPM jack output switch from output to input at random) +# SPEAKER mode actually works on the stock radio, using the stock beeper. Sort of sound OK(ish). BEEPER = SPEAKER # gruvin: Legacy support freeing of USART1 TX/RX pins [DEPRECATED] # OPTIONS STD or FREED -USART1 = FREED +USART1 = STD # gruvin: PCM-in circuit mod for JR/Spektrum (and others) compatability # Values = STD, MOD1 @@ -217,11 +218,19 @@ ifeq ($(PCB), STD) else # not PCB=STD, so ... + CPPSRC += frsky.cpp + CPPDEFS += -DPCBV3 -DFRSKY -DFRSKY_HUB ifeq ($(PCB), V3) - CPPDEFS += -DPCBV3 -DFRSKY -DBEEPSPKR + CPPDEFS += -DBEEPSPKR endif ifeq ($(PCB), V4) - CPPDEFS += -DPCBV3 -DPCBV4 -DFRSKY -DBEEPSPKR + CPPDEFS += -DPCBV4 +# Temporary hack to get stock beeper working for testing, etc ... make BEEPER=BUZZER_MOD + ifeq ($(BEEPER), BUZZER_MOD) + CPPDEFS += -DBUZZER_MOD + else + CPPDEFS += -DBEEPSPKR + endif endif endif @@ -293,7 +302,6 @@ CPPFLAGS += -O$(OPT) #CPPFLAGS += -fshort-enums #CPPFLAGS += -fno-exceptions #CPPFLAGS += -fno-unit-at-a-time -CPPFLAGS += -fno-inline-small-functions CPPFLAGS += -Wall CPPFLAGS += -Wno-strict-aliasing #CPPFLAGS += -Wstrict-prototypes @@ -304,6 +312,7 @@ CPPFLAGS += -Wno-strict-aliasing CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS)) #CPPFLAGS += $(CSTANDARD) +AVRGCCFLAGS = -fno-inline-small-functions #---------------- Assembler Options ---------------- @@ -378,11 +387,11 @@ LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB) # Type: avrdude -c ? # to get a full listing. # -AVRDUDE_PROGRAMMER = usbtiny +AVRDUDE_PROGRAMMER = avrispmkII # com1 = serial port. Use lpt1 to connect to parallel port. -AVRDUDE_PORT = /dev/ttyUSB01 +AVRDUDE_PORT = usb AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex:a AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).bin:a @@ -406,12 +415,14 @@ AVRDUDE_NO_VERIFY = -V #AVRDUDE_VERBOSE = -v -v #AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) -AVRDUDE_FLAGS = -B 1 -p $(MCU) -c $(AVRDUDE_PROGRAMMER) -AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY) +AVRDUDE_FLAGS = -B0.25 -p $(MCU) -c $(AVRDUDE_PROGRAMMER) -P $(AVRDUDE_PORT) +#AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY) AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE) AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER) - +ifeq ($(ERAZE), NO) + AVRDUDE_FLAGS += -D +endif #---------------- Debugging Options ---------------- @@ -501,7 +512,7 @@ GENDEPFLAGS = -MD -MP -MF .dep/$(@F).d # Combine all necessary flags and optional flags. # Add target processor to flags. ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS) -ALL_CPPFLAGS = -mmcu=$(MCU) -I. -x c++ $(CPPFLAGS) $(GENDEPFLAGS) +ALL_CPPFLAGS = -mmcu=$(MCU) -I. -x c++ $(CPPFLAGS) $(GENDEPFLAGS) $(AVRGCCFLAGS) ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS) SUB_VER = ${shell sh -c "grep \"SUB_VERS\" gruvin9x.h | cut -d\ -f3 | egrep -o \"[[:digit:]]\""} diff --git a/src/file.cpp b/src/file.cpp index 8aee720e5..964e2edb5 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -203,10 +203,18 @@ bool EFile::exists(uint8_t i_fileId) void EFile::swap(uint8_t i_fileId1, uint8_t i_fileId2) { +#ifdef EEPROM_ASYNC_WRITE + s_sync_write = true; +#endif + DirEnt tmp = eeFs.files[i_fileId1]; eeFs.files[i_fileId1] = eeFs.files[i_fileId2]; eeFs.files[i_fileId2] = tmp; EeFsFlush(); + +#ifdef EEPROM_ASYNC_WRITE + s_sync_write = false; +#endif } void EFile::rm(uint8_t i_fileId) diff --git a/src/gruvin9x.cpp b/src/gruvin9x.cpp index fdf573b22..0569ce7f3 100644 --- a/src/gruvin9x.cpp +++ b/src/gruvin9x.cpp @@ -721,19 +721,6 @@ uint8_t checkTrim(uint8_t event) } #ifndef SIMU -class AutoLock -{ - uint8_t m_saveFlags; -public: - AutoLock(){ - m_saveFlags = SREG; - cli(); - }; - ~AutoLock(){ - if(m_saveFlags & (1<49) { + if (g_eeGeneral.inactivityTimer && g_vbat100mV>50) { inacCounter++; uint16_t tsum = 0; for(uint8_t i=0;i<4;i++) tsum += anaIn(i)/64; // reduce sensitivity @@ -1617,7 +1603,7 @@ Gruvin: static uint8_t s_batCheck; s_batCheck+=32; - if(s_batCheck==0 && g_vbat100mV49) { + if(s_batCheck==0 && g_vbat100mV50) { beepErr(); if (g_eeGeneral.flashBeep) g_LightOffCounter = FLASH_DURATION; } @@ -2196,7 +2182,11 @@ int main(void) uint8_t cModel = g_eeGeneral.currModel; +#if defined (PCBV3) + if (~MCUSR & (1 << WDRF)) { +#else if (~MCUCSR & (1 << WDRF)) { +#endif doSplash(); checkLowEEPROM(); diff --git a/src/gruvin9x.h b/src/gruvin9x.h index fbafb081b..00c8cb11d 100644 --- a/src/gruvin9x.h +++ b/src/gruvin9x.h @@ -576,13 +576,11 @@ void eeDirty(uint8_t msk); inline void eeFlush() { theFile.flush(); } #endif void eeCheck(bool immediately=false); -//void eeWriteGeneral(); void eeReadAll(); bool eeModelExists(uint8_t id); uint16_t eeLoadModelName(uint8_t id, char *name); void eeLoadModel(uint8_t id); -//void eeSaveModel(uint8_t id); -bool eeDuplicateModel(uint8_t id); +int8_t eeDuplicateModel(uint8_t id, bool down=true); ///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) diff --git a/src/main_views.cpp b/src/main_views.cpp index 7f67532f5..376ccb402 100644 --- a/src/main_views.cpp +++ b/src/main_views.cpp @@ -53,9 +53,11 @@ void menuMainView(uint8_t event) uint8_t view = (switchView == 255 ? g_eeGeneral.view : switchView); +#ifdef FRSKY bool telemViewSw = isFunctionActive(FUNC_VIEW_TELEMETRY); if (switchView == 255 && telemViewSw) { view = switchView = e_telemetry + ALTERNATE; } if (switchView != 255 && !telemViewSw) { view = g_eeGeneral.view; switchView = 255; } +#endif uint8_t view_base = view & 0x0f; @@ -154,6 +156,7 @@ void menuMainView(uint8_t event) if (!instantTrimSwLock && trimSw) instantTrim(); instantTrimSwLock = trimSw; +#ifdef FRSKY if (view_base == e_telemetry && view > ALTERNATE) { putsModelName(0, 0, g_model.name, g_eeGeneral.currModel, 0); uint8_t att = (g_vbat100mV < g_eeGeneral.vBatWarn ? BLINK : 0); @@ -164,7 +167,9 @@ void menuMainView(uint8_t event) } lcd_filled_rect(0, 0, DISPLAY_W, 8); } - else { + else +#endif + { uint8_t phase = getFlightPhase(); lcd_putsnAtt(6*FW+2, 2*FH, g_model.phaseData[phase].name, sizeof(g_model.phaseData[phase].name), ZCHAR); diff --git a/src/model_menus.cpp b/src/model_menus.cpp index 4873685da..880a44cb4 100644 --- a/src/model_menus.cpp +++ b/src/model_menus.cpp @@ -90,104 +90,6 @@ MenuFuncP_PROGMEM APM menuTabModel[] = { #endif }; -void menuProcModelSelect(uint8_t event) // TODO lignes sur tout du long -{ - TITLE("MODELSEL"); - int8_t subOld = m_posVert; - if (!check_submenu_simple(event, MAX_MODELS-1)) return; - -#ifdef EEPROM_ASYNC_WRITE - // flush eeprom write so that it's possible to load model names - eeFlush(); -#endif - - lcd_puts_P( 9*FW, 0, PSTR("free")); - lcd_outdezAtt( 17*FW, 0, EeFsGetFree(),0); - - DisplayScreenIndex(e_ModelSelect, DIM(menuTabModel), INVERS); - - int8_t sub = m_posVert; - static uint8_t sel_editMode; - - switch(event) - { - //case EVT_KEY_FIRST(KEY_MENU): - case EVT_KEY_FIRST(KEY_EXIT): - if(sel_editMode){ - sel_editMode = false; - beepKey(); - killEvents(event); - eeCheck(true); // force writing of current model data before this is changed - eeLoadModel(g_eeGeneral.currModel = m_posVert); - STORE_GENERALVARS; - break; - } - //fallthrough - case EVT_KEY_FIRST(KEY_LEFT): - case EVT_KEY_FIRST(KEY_RIGHT): - if(g_eeGeneral.currModel != m_posVert) - { - killEvents(event); - g_eeGeneral.currModel = m_posVert; - eeCheck(true); // force writing of current model data before this is changed - eeLoadModel(g_eeGeneral.currModel); - STORE_GENERALVARS; - beepWarn1(); - } - //case EXIT handled in checkExit - if(event==EVT_KEY_FIRST(KEY_LEFT)) chainMenu(menuTabModel[DIM(menuTabModel)-1]); - if(event==EVT_KEY_FIRST(KEY_RIGHT)) chainMenu(menuProcModel); - return; - case EVT_KEY_FIRST(KEY_MENU): - sel_editMode = true; - beepKey(); - break; - case EVT_KEY_LONG(KEY_MENU): - if(sel_editMode){ - // message(PSTR("Duplicating model")); - eeCheck(true); // force writing of current model data before this is changed - if (eeDuplicateModel(sub)) { - beepKey(); - sel_editMode = false; - } - else { - beepWarn(); - } - } - break; - - case EVT_ENTRY: - sel_editMode = false; - m_posVert = sub = g_eeGeneral.currModel; - break; - } - if(sel_editMode && subOld!=sub){ - eeCheck(true); // force writing of current model data before this is changed -#ifdef EEPROM_ASYNC_WRITE - s_sync_write = true; -#endif - EFile::swap(FILE_MODEL(subOld),FILE_MODEL(sub)); -#ifdef EEPROM_ASYNC_WRITE - s_sync_write = false; -#endif - } - - if(sub-s_pgOfs < 1) s_pgOfs = max(0,sub-1); - else if(sub-s_pgOfs >4 ) s_pgOfs = min(MAX_MODELS-6,sub-4); - for(uint8_t i=0; i<6; i++){ - uint8_t y=(i+2)*FH; - uint8_t k=i+s_pgOfs; - lcd_outdezNAtt( 3*FW, y, k+1, LEADING0+((sub==k) ? INVERS : 0), 2); - if(k==g_eeGeneral.currModel) lcd_putc(1, y,'*'); - char name[sizeof(g_model.name)]; - uint16_t size = eeLoadModelName(k, name); - if (size) { - putsModelName(4*FW, y, name, k, ((sub==k) ? (sel_editMode ? INVERS : 0 ) : 0)); - lcd_outdezAtt(20*FW, y, size, ((sub==k) ? (sel_editMode ? INVERS : 0 ) : 0)); - } - } -} - const prog_char * s_warning = 0; const prog_char * s_warning_info; uint8_t s_warning_info_len; @@ -214,24 +116,203 @@ void displayWarning(uint8_t event) void displayConfirmation(uint8_t event) { - if (s_warning) { - s_confirmation = false; - lcd_filled_rect(10, 16, 108, 40, WHITE); - lcd_rect(10, 16, 108, 40); - lcd_puts_P(16, 3*FH, s_warning); - if (s_warning_info) - lcd_putsnAtt(16, 4*FH, s_warning_info, s_warning_info_len, ZCHAR); - lcd_puts_P(16, 5*FH, PSTR("[MENU] [EXIT]")); + s_confirmation = false; + lcd_filled_rect(10, 16, 108, 40, WHITE); + lcd_rect(10, 16, 108, 40); + lcd_puts_P(16, 3*FH, s_warning); + if (s_warning_info) + lcd_putsnAtt(16, 4*FH, s_warning_info, s_warning_info_len, ZCHAR); + lcd_puts_P(16, 5*FH, PSTR("[MENU] [EXIT]")); - switch(event) { - case EVT_KEY_FIRST(KEY_MENU): - s_confirmation = true; - // no break - case EVT_KEY_FIRST(KEY_EXIT): - killEvents(event); - s_warning = 0; + switch(event) { + case EVT_KEY_FIRST(KEY_MENU): + s_confirmation = true; + // no break + case EVT_KEY_FIRST(KEY_EXIT): + killEvents(event); + s_warning = 0; + break; + } +} + +#define COPY_MODE 1 +#define MOVE_MODE 2 +static uint8_t s_copyMode = 0; +static int8_t s_copySrcRow; +static int8_t s_copyTgtOfs; + +void menuProcModelSelect(uint8_t event) +{ + char name[sizeof(g_model.name)]; + + TITLE("MODELSEL"); + +#ifdef EEPROM_ASYNC_WRITE + // flush eeprom write + eeFlush(); +#endif + + if (s_confirmation) { + EFile::rm(FILE_MODEL(m_posVert)); // delete file + s_confirmation = 0; + s_copyMode = 0; + } + + uint8_t _event = (s_warning ? 0 : event); + uint8_t __event = _event; + + if (s_copyMode || !EFile::exists(FILE_MODEL(g_eeGeneral.currModel))) { + if ((_event & 0x1f) == KEY_EXIT) + __event -= KEY_EXIT; + } + + int8_t oldSub = m_posVert; + if (!check_submenu_simple(__event, MAX_MODELS-1)) return; + int8_t sub = m_posVert; + + lcd_puts_P( 9*FW, 0, PSTR("free")); + lcd_outdezAtt( 17*FW, 0, EeFsGetFree(),0); + + DisplayScreenIndex(e_ModelSelect, DIM(menuTabModel), INVERS); + + switch(_event) + { + case EVT_ENTRY: + m_posVert = sub = g_eeGeneral.currModel; + s_copyMode = 0; + s_copyTgtOfs = 0; + s_copySrcRow = -1; break; + case EVT_KEY_LONG(KEY_EXIT): + if (s_copyMode && s_copyTgtOfs == 0 && g_eeGeneral.currModel != sub && EFile::exists(FILE_MODEL(sub))) { + s_warning = PSTR("DELETE MODEL"); + killEvents(_event); + break; + } + // 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; + } + EFile::swap(FILE_MODEL(sub), FILE_MODEL(m_posVert)); + 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_copyMode = 0; + killEvents(_event); + break; + case EVT_KEY_BREAK(KEY_MENU): + if (EFile::exists(FILE_MODEL(sub)) && !s_copyTgtOfs) { + s_copyMode = (s_copyMode == COPY_MODE ? MOVE_MODE : COPY_MODE); + s_copySrcRow = -1; + break; + } + // no break + case EVT_KEY_LONG(KEY_MENU): + if (s_copyTgtOfs) { + s_copyTgtOfs = 0; + } + else { + eeCheck(true); // force writing of current model data before this is changed + eeLoadModel(sub); + if (g_eeGeneral.currModel != sub) { + g_eeGeneral.currModel = sub; + STORE_GENERALVARS; + } + } + s_copyMode = 0; + killEvents(_event); + break; + case EVT_KEY_FIRST(KEY_LEFT): + case EVT_KEY_FIRST(KEY_RIGHT): + if (sub == g_eeGeneral.currModel) { + if (!EFile::exists(FILE_MODEL(sub))) { + eeCheck(true); // force writing of current model data before this is changed + eeLoadModel(sub); + } + chainMenu(_event == EVT_KEY_FIRST(KEY_RIGHT) ? menuProcModel : menuTabModel[DIM(menuTabModel)-1]); + return; + } + beepWarn(); + break; + 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 (s_copySrcRow < 0 && s_copyMode==COPY_MODE) { + s_copySrcRow = sub+next_ofs; + // insert a model (in the first empty slot above / below) + m_posVert = eeDuplicateModel(s_copySrcRow, _event==EVT_KEY_FIRST(KEY_DOWN)); + if (m_posVert == (uint8_t)-1) { + m_posVert = sub; + } + next_ofs = 0; + sub = m_posVert; + } + else { + // only swap the model with its neighbor + EFile::swap(FILE_MODEL(oldSub), FILE_MODEL(sub)); + 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; + } + + 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); + 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 (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) 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); + lcd_filled_rect(9, y, DISPLAY_W-1-9, 7); + } + } + + if (s_warning) { + eeLoadModelName(sub, name); + s_warning_info = name; + s_warning_info_len = sizeof(g_model.name); + displayConfirmation(event); } } @@ -271,36 +352,9 @@ void EditName(uint8_t x, uint8_t y, char *name, uint8_t size, uint8_t event, boo } #define PARAM_OFS (9*FW) -void menuProcModel(uint8_t _event) +void menuProcModel(uint8_t event) { - uint8_t event = (s_warning ? 0 : _event); - - if (s_confirmation) { - uint8_t i = g_eeGeneral.currModel; - -#ifdef EEPROM_ASYNC_WRITE - // flush eeprom write - eeFlush(); -#endif - EFile::rm(FILE_MODEL(i)); // delete file - - while (!EFile::exists(FILE_MODEL(i))) { - i--; - if (i>MAX_MODELS) i=MAX_MODELS-1; - if (i==g_eeGeneral.currModel) { - i=0; - break; - } - } - g_eeGeneral.currModel = i; - STORE_GENERALVARS; - eeLoadModel(i); // load default values - s_confirmation = 0; - chainMenu(menuProcModelSelect); - return; - } - - MENU("SETUP", menuTabModel, e_Model, 11, {0,sizeof(g_model.name)-1,3,3,0,0,0,1,6,3/*, 0*/}); + MENU("SETUP", menuTabModel, e_Model, 10, {0,sizeof(g_model.name)-1,3,3,0,0,0,1,6,3}); uint8_t sub = m_posVert; uint8_t y = 1*FH; @@ -430,21 +484,7 @@ void menuProcModel(uint8_t _event) break; } if((y+=FH)>7*FH) return; - }subN++; - - if(s_pgOfs= EEPROM_ER9X_MIN && g_eeGeneral.myVers <= EEPROM_ER9X_MAX)) { alert(g_eeGeneral.myVers == EEPROM_VER_r584 ? PSTR("EEprom Data v3") : PSTR("EEprom Data Er9x"), true); message(PSTR("EEPROM Converting")); @@ -69,6 +75,9 @@ uint8_t Translate() if (g_eeGeneral.lightSw == -MAX_SWITCH+6) g_eeGeneral.lightSw -= 6; } + else { + g_eeGeneral.inactivityTimer += 10; + } g_eeGeneral.view = 0; // will not translate the view index EEPROM_V3::EEGeneral *old = (EEPROM_V3::EEGeneral *)&g_eeGeneral; g_eeGeneral.disableMemoryWarning = old->disableMemoryWarning; @@ -211,7 +220,7 @@ bool eeLoadGeneral() uint8_t sz = 0; if (theFile.readRlc((uint8_t*)&g_eeGeneral, 1) == 1) { - theFile.openRlc(FILE_GENERAL); + theFile.openRlc(FILE_GENERAL); // TODO include this openRlc inside readRlc if (g_eeGeneral.myVers == EEPROM_VER) { sz = theFile.readRlc((uint8_t*)&g_eeGeneral, sizeof(g_eeGeneral)); } @@ -288,14 +297,14 @@ void eeLoadModel(uint8_t id) } } -bool eeDuplicateModel(uint8_t id) +int8_t eeDuplicateModel(uint8_t id, bool down) { - uint8_t i; - for( i=id+1; i