From 2d4e98d15db8af8723521c2a654c3dd0b98f6688 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Fri, 30 Aug 2019 15:46:57 +0200 Subject: [PATCH] Bsongis/ram saving (#6685) RAM saving. Stacks reduced to have some more RAM available than 2.2 on all boards --- radio/src/audio.cpp | 2 +- radio/src/gui/128x64/gui.h | 4 - radio/src/gui/128x64/view_channels.cpp | 28 +++--- radio/src/gui/128x64/view_statistics.cpp | 2 +- radio/src/gui/212x64/gui.h | 4 - radio/src/gui/212x64/model_failsafe.cpp | 61 ++++++----- radio/src/gui/212x64/view_channels.cpp | 28 +++--- radio/src/gui/480x272/menus.cpp | 16 +-- radio/src/gui/480x272/menus.h | 4 - radio/src/gui/480x272/view_text.cpp | 84 +--------------- radio/src/gui/common/stdlcd/model_notes.cpp | 4 +- radio/src/gui/common/stdlcd/view_text.cpp | 100 +++---------------- radio/src/gui/gui_common.h | 1 + radio/src/keys.cpp | 2 +- radio/src/main.cpp | 11 +- radio/src/opentx.cpp | 25 ++--- radio/src/opentx.h | 58 ++++++----- radio/src/pulses/pulses.h | 2 +- radio/src/sdcard.cpp | 68 +++++++++++++ radio/src/sdcard.h | 2 + radio/src/switches.cpp | 9 +- radio/src/targets/horus/board.h | 4 +- radio/src/targets/sky9x/lcd_driver.cpp | 2 +- radio/src/targets/taranis/trainer_driver.cpp | 3 - radio/src/tasks.h | 10 +- radio/src/telemetry/telemetry.cpp | 14 --- radio/src/telemetry/telemetry.h | 5 - tools/extract-map.py | 48 +++++++++ 28 files changed, 271 insertions(+), 330 deletions(-) create mode 100755 tools/extract-map.py diff --git a/radio/src/audio.cpp b/radio/src/audio.cpp index 5116003b9..2737592cb 100644 --- a/radio/src/audio.cpp +++ b/radio/src/audio.cpp @@ -529,7 +529,7 @@ void audioTask(void * pdata) RTOS_WAIT_MS(1000); // 1s #endif - if (!unexpectedShutdown) { + if (!globalData.unexpectedShutdown) { AUDIO_HELLO(); } diff --git a/radio/src/gui/128x64/gui.h b/radio/src/gui/128x64/gui.h index be69f27f7..f131c0e85 100644 --- a/radio/src/gui/128x64/gui.h +++ b/radio/src/gui/128x64/gui.h @@ -231,15 +231,11 @@ void drawStatusLine(); #define drawStatusLine() #endif -#define TEXT_FILENAME_MAXLEN 40 -extern char s_text_file[TEXT_FILENAME_MAXLEN]; void menuTextView(event_t event); void pushMenuTextView(const char *filename); void pushModelNotes(); void readModelNotes(); -#define LABEL(...) (uint8_t)-1 - #define CURSOR_MOVED_LEFT(event) (IS_ROTARY_LEFT(event) || EVT_KEY_MASK(event) == KEY_LEFT) #define CURSOR_MOVED_RIGHT(event) (IS_ROTARY_RIGHT(event) || EVT_KEY_MASK(event) == KEY_RIGHT) diff --git a/radio/src/gui/128x64/view_channels.cpp b/radio/src/gui/128x64/view_channels.cpp index a17bfa757..231805ead 100644 --- a/radio/src/gui/128x64/view_channels.cpp +++ b/radio/src/gui/128x64/view_channels.cpp @@ -22,33 +22,35 @@ void menuChannelsView(event_t event) { - static bool longNames = false; bool newLongNames = false; - static bool secondPage = false; - static bool mixersView = false; uint8_t ch; - switch(event) - { + switch (event) { + case EVT_ENTRY: + memclear(&reusableBuffer.viewChannels, sizeof(reusableBuffer.viewChannels)); + break; + case EVT_KEY_BREAK(KEY_EXIT): popMenu(); break; + case EVT_KEY_FIRST(KEY_RIGHT): case EVT_KEY_FIRST(KEY_LEFT): - secondPage = !secondPage; + reusableBuffer.viewChannels.secondPage = !reusableBuffer.viewChannels.secondPage; break; + case EVT_KEY_FIRST(KEY_ENTER): - mixersView = !mixersView; + reusableBuffer.viewChannels.mixersView = !reusableBuffer.viewChannels.mixersView; break; } - if (secondPage) + if (reusableBuffer.viewChannels.secondPage) ch = 16; else ch = 0; - if (mixersView) { + if (reusableBuffer.viewChannels.mixersView) { lcdDrawTextAlignedCenter(0, TR_MIXERS_MONITOR); } else { @@ -67,13 +69,13 @@ void menuChannelsView(event_t event) // Channels for (uint8_t line=0; line<8; line++) { uint8_t y = 9+line*7; - int32_t val = (mixersView) ? ex_chans[ch] : channelOutputs[ch]; + int32_t val = (reusableBuffer.viewChannels.mixersView) ? ex_chans[ch] : channelOutputs[ch]; uint8_t ofs = (col ? 0 : 1); // Channel name if present, number if not uint8_t lenLabel = ZLEN(g_model.limitData[ch].name); if (lenLabel > 4) { - newLongNames = longNames = true; + newLongNames = reusableBuffer.viewChannels.longNames = true; } if (lenLabel > 0) @@ -86,7 +88,7 @@ void menuChannelsView(event_t event) uint8_t wbar = (longNames ? 54 : 64); lcdDrawNumber(x+LCD_W/2-3-wbar-ofs, y+1, PPM_CH_CENTER(ch)+val/2, TINSIZE|RIGHT); #elif defined(PPM_UNIT_PERCENT_PREC1) - uint8_t wbar = (longNames ? 48 : 58); + uint8_t wbar = (reusableBuffer.viewChannels.longNames ? 48 : 58); lcdDrawNumber(x+LCD_W/2-3-wbar-ofs, y+1, calcRESXto1000(val), PREC1|TINSIZE|RIGHT); #else uint8_t wbar = (longNames ? 54 : 64); @@ -105,5 +107,5 @@ void menuChannelsView(event_t event) } } - longNames = newLongNames; + reusableBuffer.viewChannels.longNames = newLongNames; } diff --git a/radio/src/gui/128x64/view_statistics.cpp b/radio/src/gui/128x64/view_statistics.cpp index 4e132a1eb..d573bfc2c 100644 --- a/radio/src/gui/128x64/view_statistics.cpp +++ b/radio/src/gui/128x64/view_statistics.cpp @@ -160,7 +160,7 @@ void menuStatisticsDebug(event_t event) if (IS_RESET_REASON_WATCHDOG()) { lcdDrawText(LCD_W-8*FW, 0, "WATCHDOG"); } - else if (unexpectedShutdown) { + else if (globalData.unexpectedShutdown) { lcdDrawText(LCD_W-13*FW, 0, "UNEXP.SHTDOWN"); } #endif diff --git a/radio/src/gui/212x64/gui.h b/radio/src/gui/212x64/gui.h index 14d9c6978..443ac45b4 100644 --- a/radio/src/gui/212x64/gui.h +++ b/radio/src/gui/212x64/gui.h @@ -264,8 +264,6 @@ extern char statusLineMsg[STATUS_LINE_LENGTH]; void showStatusLine(); void drawStatusLine(); -#define TEXT_FILENAME_MAXLEN 40 -extern char s_text_file[TEXT_FILENAME_MAXLEN]; void menuTextView(event_t event); void pushMenuTextView(const char *filename); void pushModelNotes(); @@ -273,8 +271,6 @@ void readModelNotes(); void menuChannelsView(event_t event); -#define LABEL(...) (uint8_t)-1 - #if defined(ROTARY_ENCODER_NAVIGATION) #define CURSOR_MOVED_LEFT(event) (event==EVT_ROTARY_LEFT) #define CURSOR_MOVED_RIGHT(event) (event==EVT_ROTARY_RIGHT) diff --git a/radio/src/gui/212x64/model_failsafe.cpp b/radio/src/gui/212x64/model_failsafe.cpp index 3fdc2ee28..939e7927a 100644 --- a/radio/src/gui/212x64/model_failsafe.cpp +++ b/radio/src/gui/212x64/model_failsafe.cpp @@ -24,46 +24,45 @@ extern uint8_t g_moduleIdx; void menuModelFailsafe(event_t event) { - static uint8_t maxNameLen = 4; - static int8_t lastModel = g_eeGeneral.currModel; const coord_t barH = (LCD_H - FH) / 8 - 1; const int lim = (g_model.extendedLimits ? (512 * LIMIT_EXT_PERCENT / 100) : 512) * 2; const uint8_t channelStart = g_model.moduleData[g_moduleIdx].channelsStart; uint8_t cols = 1; uint8_t colW = LCD_W; - if (lastModel != g_eeGeneral.currModel) { - lastModel = g_eeGeneral.currModel; - maxNameLen = 4; - } + switch(event) { + case EVT_ENTRY: + reusableBuffer.modelFailsafe.maxNameLen = 4; + break; - if (event == EVT_KEY_LONG(KEY_ENTER)) { - killEvents(event); - event = 0; + case EVT_KEY_LONG(KEY_ENTER): + killEvents(event); + event = 0; - if (menuVerticalPosition < sentModuleChannels(g_moduleIdx)) { - if (s_editMode) { - g_model.failsafeChannels[menuVerticalPosition] = channelOutputs[menuVerticalPosition+channelStart]; - s_editMode = 0; + if (menuVerticalPosition < sentModuleChannels(g_moduleIdx)) { + if (s_editMode) { + g_model.failsafeChannels[menuVerticalPosition] = channelOutputs[menuVerticalPosition+channelStart]; + s_editMode = 0; + } + else { + int16_t * failsafe = &g_model.failsafeChannels[menuVerticalPosition]; + if (*failsafe < FAILSAFE_CHANNEL_HOLD) + *failsafe = FAILSAFE_CHANNEL_HOLD; + else if (*failsafe == FAILSAFE_CHANNEL_HOLD) + *failsafe = FAILSAFE_CHANNEL_NOPULSE; + else + *failsafe = 0; + } } else { - int16_t * failsafe = &g_model.failsafeChannels[menuVerticalPosition]; - if (*failsafe < FAILSAFE_CHANNEL_HOLD) - *failsafe = FAILSAFE_CHANNEL_HOLD; - else if (*failsafe == FAILSAFE_CHANNEL_HOLD) - *failsafe = FAILSAFE_CHANNEL_NOPULSE; - else - *failsafe = 0; + // "Outputs => Failsafe" menu item + setCustomFailsafe(g_moduleIdx); } - } - else { - // "Outputs => Failsafe" menu item - setCustomFailsafe(g_moduleIdx); - } - storageDirty(EE_MODEL); - AUDIO_WARNING1(); - SEND_FAILSAFE_NOW(g_moduleIdx); + storageDirty(EE_MODEL); + AUDIO_WARNING1(); + SEND_FAILSAFE_NOW(g_moduleIdx); + break; } SIMPLE_SUBMENU_NOTITLE(sentModuleChannels(g_moduleIdx) + 1); @@ -95,7 +94,7 @@ void menuModelFailsafe(event_t event) const int32_t channelValue = channelOutputs[ch+channelStart]; int32_t failsafeValue = g_model.failsafeChannels[8*col+line]; uint8_t lenLabel = ZLEN(g_model.limitData[ch+channelStart].name); - uint8_t barW = colW - FW * maxNameLen - FWNUM * 3; // default bar width + uint8_t barW = colW - FW * reusableBuffer.modelFailsafe.maxNameLen - FWNUM * 3; // default bar width #if defined(PPM_UNIT_PERCENT_PREC1) barW -= FWNUM + 1; @@ -104,8 +103,8 @@ void menuModelFailsafe(event_t event) // Channel name if present, number if not if (lenLabel > 0) { - if (lenLabel > maxNameLen) - maxNameLen = lenLabel; + if (lenLabel > reusableBuffer.modelFailsafe.maxNameLen) + reusableBuffer.modelFailsafe.maxNameLen = lenLabel; lcdDrawSizedText(x - colW, y, g_model.limitData[ch+channelStart].name, sizeof(g_model.limitData[ch+channelStart].name), ZCHAR | SMLSIZE); } else { diff --git a/radio/src/gui/212x64/view_channels.cpp b/radio/src/gui/212x64/view_channels.cpp index c1eff98f7..4b34f7f4f 100644 --- a/radio/src/gui/212x64/view_channels.cpp +++ b/radio/src/gui/212x64/view_channels.cpp @@ -22,44 +22,46 @@ void menuChannelsView(event_t event) { - static bool longNames = false; - static bool secondPage = false; - static bool mixersView = false; uint8_t ch = 0; - uint8_t wbar = (longNames ? 54 : 64); + uint8_t wbar = (reusableBuffer.viewChannels.longNames ? 54 : 64); int16_t limits = 512 * 2; #if defined(PPM_UNIT_PERCENT_PREC1) wbar -= 6; #endif - switch(event) - { + switch(event) { + case EVT_ENTRY: + memclear(&reusableBuffer.viewChannels, sizeof(reusableBuffer.viewChannels)); + break; + case EVT_KEY_BREAK(KEY_EXIT): popMenu(); break; + case EVT_KEY_FIRST(KEY_RIGHT): case EVT_KEY_FIRST(KEY_LEFT): #if defined(ROTARY_ENCODER_NAVIGATION) case EVT_ROTARY_LEFT: case EVT_ROTARY_RIGHT: #endif - secondPage = !secondPage; + reusableBuffer.viewChannels.secondPage = !reusableBuffer.viewChannels.secondPage; break; + case EVT_KEY_FIRST(KEY_ENTER): - mixersView = !mixersView; + reusableBuffer.viewChannels.mixersView = !reusableBuffer.viewChannels.mixersView; break; } - if (secondPage) + if (reusableBuffer.viewChannels.secondPage) ch = 16; - if (mixersView) + if (reusableBuffer.viewChannels.mixersView) limits *= 2; // this could be handled nicer, but slower, by checking actual range for this mixer else if (g_model.extendedLimits) limits *= LIMIT_EXT_PERCENT / 100; - if (mixersView) + if (reusableBuffer.viewChannels.mixersView) lcdDrawTextAlignedCenter(0, TR_MIXERS_MONITOR); else lcdDrawTextAlignedCenter(0, TR_CHANNELS_MONITOR); @@ -76,13 +78,13 @@ void menuChannelsView(event_t event) // Channels for (uint8_t line=0; line < 8; line++) { const uint8_t y = 9 + line * 7; - const int32_t val = mixersView ? ex_chans[ch] : channelOutputs[ch]; + const int32_t val = reusableBuffer.viewChannels.mixersView ? ex_chans[ch] : channelOutputs[ch]; const uint8_t lenLabel = ZLEN(g_model.limitData[ch].name); // Channel name if present, number if not if (lenLabel > 0) { if (lenLabel > 4) - longNames = true; + reusableBuffer.viewChannels.longNames = true; lcdDrawSizedText(x+1-ofs, y, g_model.limitData[ch].name, sizeof(g_model.limitData[ch].name), ZCHAR | SMLSIZE); } else { diff --git a/radio/src/gui/480x272/menus.cpp b/radio/src/gui/480x272/menus.cpp index c1b507930..c7963191e 100644 --- a/radio/src/gui/480x272/menus.cpp +++ b/radio/src/gui/480x272/menus.cpp @@ -78,11 +78,11 @@ void readModelNotes() { LED_ERROR_BEGIN(); - strcpy(s_text_file, MODELS_PATH "/"); - char *buf = strcat_currentmodelname(&s_text_file[sizeof(MODELS_PATH)]); + strcpy(reusableBuffer.viewText.filename, MODELS_PATH "/"); + char *buf = strcat_currentmodelname(&reusableBuffer.viewText.filename[sizeof(MODELS_PATH)]); strcpy(buf, TEXT_EXT); - if (!isFileAvailable(s_text_file)) { - char *buf = strAppendFilename(&s_text_file[sizeof(MODELS_PATH)], g_eeGeneral.currModelFilename, LEN_MODEL_FILENAME); + if (!isFileAvailable(reusableBuffer.viewText.filename)) { + char *buf = strAppendFilename(&reusableBuffer.viewText.filename[sizeof(MODELS_PATH)], g_eeGeneral.currModelFilename, LEN_MODEL_FILENAME); strcpy(buf, TEXT_EXT); } @@ -103,11 +103,11 @@ void readModelNotes() bool menuModelNotes(event_t event) { if (event == EVT_ENTRY) { - strcpy(s_text_file, MODELS_PATH "/"); - char *buf = strcat_currentmodelname(&s_text_file[sizeof(MODELS_PATH)]); + strcpy(reusableBuffer.viewText.filename, MODELS_PATH "/"); + char *buf = strcat_currentmodelname(&reusableBuffer.viewText.filename[sizeof(MODELS_PATH)]); strcpy(buf, TEXT_EXT); - if (!isFileAvailable(s_text_file)) { - char *buf = strAppendFilename(&s_text_file[sizeof(MODELS_PATH)], g_eeGeneral.currModelFilename, LEN_MODEL_FILENAME); + if (!isFileAvailable(reusableBuffer.viewText.filename)) { + char * buf = strAppendFilename(&reusableBuffer.viewText.filename[sizeof(MODELS_PATH)], g_eeGeneral.currModelFilename, LEN_MODEL_FILENAME); strcpy(buf, TEXT_EXT); } } diff --git a/radio/src/gui/480x272/menus.h b/radio/src/gui/480x272/menus.h index 6b3242c7a..3a87fbbc4 100644 --- a/radio/src/gui/480x272/menus.h +++ b/radio/src/gui/480x272/menus.h @@ -589,14 +589,10 @@ inline void POPUP_CONFIRMATION(const char *s, void (* confirmHandler)(const char popupMenuHandler = confirmHandler; } -#define TEXT_FILENAME_MAXLEN 40 -extern char s_text_file[TEXT_FILENAME_MAXLEN]; void pushMenuTextView(const char * filename); void pushModelNotes(); void readModelNotes(); -#define LABEL(...) (uint8_t)-1 - #define CURSOR_MOVED_LEFT(event) (event==EVT_ROTARY_LEFT || EVT_KEY_MASK(event) == KEY_LEFT) #define CURSOR_MOVED_RIGHT(event) (event==EVT_ROTARY_RIGHT || EVT_KEY_MASK(event) == KEY_RIGHT) #define REPEAT_LAST_CURSOR_MOVE(last, refresh) { if (CURSOR_MOVED_RIGHT(event)) menuHorizontalPosition = (menuHorizontalPosition >= (last) ? 0 : menuHorizontalPosition + 1); else menuHorizontalPosition = (menuHorizontalPosition <= (0) ? last : menuHorizontalPosition - 1); if (refresh) putEvent(EVT_REFRESH); } diff --git a/radio/src/gui/480x272/view_text.cpp b/radio/src/gui/480x272/view_text.cpp index 10eb8f08f..b4aee0f8e 100644 --- a/radio/src/gui/480x272/view_text.cpp +++ b/radio/src/gui/480x272/view_text.cpp @@ -20,80 +20,6 @@ #include "opentx.h" -#define TEXT_FILE_MAXSIZE 2048 - -char s_text_file[TEXT_FILENAME_MAXLEN]; -char s_text_screen[NUM_BODY_LINES][LCD_COLS+1]; - -void readTextFile(int & lines_count) -{ - FIL file; - int result; - char c; - unsigned int sz; - int line_length = 0; - int escape = 0; - char escape_chars[2]; - int current_line = 0; - - memset(s_text_screen, 0, sizeof(s_text_screen)); - - result = f_open(&file, s_text_file, FA_OPEN_EXISTING | FA_READ); - if (result == FR_OK) { - for (int i=0; i=menuVerticalOffset && current_line-menuVerticalOffset0 && escape<4) { - escape_chars[escape-1] = c; - if (escape == 2 && !strncmp(escape_chars, "up", 2)) { - c = '\300'; - escape = 0; - } - else if (escape == 2 && !strncmp(escape_chars, "dn", 2)) { - c = '\301'; - escape = 0; - } - else if (escape == 3) { - int val = atoi(escape_chars); - if (val >= 200 && val < 225) { - c = '\200' + val-200; - } - escape = 0; - } - else { - escape++; - continue; - } - } - else if (c=='~') { - c = 'z'+1; - } - else if (c=='\t') { - c = 0x1D; //tab - } - escape = 0; - s_text_screen[current_line-menuVerticalOffset][line_length++] = c; - } - } - if (c != '\n') { - current_line += 1; - } - f_close(&file); - } - - if (lines_count == 0) { - lines_count = current_line; - } -} - bool menuTextView(event_t event) { static int lines_count; @@ -104,7 +30,7 @@ bool menuTextView(event_t event) case EVT_ENTRY: menuVerticalOffset = 0; lines_count = 0; - readTextFile(lines_count); + sdReadTextFile(reusableBuffer.viewText.filename, reusableBuffer.viewText.lines, lines_count); break; case EVT_ROTARY_LEFT: @@ -112,7 +38,7 @@ bool menuTextView(event_t event) break; else menuVerticalOffset--; - readTextFile(lines_count); + sdReadTextFile(reusableBuffer.viewText.filename, reusableBuffer.viewText.lines, lines_count); break; case EVT_ROTARY_RIGHT: @@ -120,7 +46,7 @@ bool menuTextView(event_t event) break; else ++menuVerticalOffset; - readTextFile(lines_count); + sdReadTextFile(reusableBuffer.viewText.filename, reusableBuffer.viewText.lines, lines_count); break; case EVT_KEY_FIRST(KEY_EXIT): @@ -129,7 +55,7 @@ bool menuTextView(event_t event) } for (int i=0; i=menuVerticalOffset && current_line-menuVerticalOffset0 && escape<4) { - escape_chars[escape-1] = c; - if (escape == 2 && !strncmp(escape_chars, "up", 2)) { - c = '\300'; - escape = 0; - } - else if (escape == 2 && !strncmp(escape_chars, "dn", 2)) { - c = '\301'; - escape = 0; - } - else if (escape == 3) { - int val = atoi(escape_chars); - if (val >= 200 && val < 225) { - c = '\200' + val-200; - } - escape = 0; - } - else { - escape++; - continue; - } - } - else if (c=='~') { - c = 'z'+1; - } - else if (c=='\t') { - c = 0x1D; //tab - } - escape = 0; - s_text_screen[current_line-menuVerticalOffset][line_length++] = c; - } - } - if (c != '\n') { - current_line += 1; - } - f_close(&file); - } - - if (lines_count == 0) { - lines_count = current_line; - } -} - #if defined(ROTARY_ENCODER_NAVIGATION) #define EVT_KEY_NEXT_LINE EVT_ROTARY_RIGHT #define EVT_KEY_PREVIOUS_LINE EVT_ROTARY_LEFT @@ -106,8 +32,8 @@ void readModelNotes() { LED_ERROR_BEGIN(); - strcpy(s_text_file, MODELS_PATH "/"); - char *buf = strcat_modelname(&s_text_file[sizeof(MODELS_PATH)], g_eeGeneral.currModel); + strcpy(reusableBuffer.viewText.filename, MODELS_PATH "/"); + char *buf = strcat_modelname(&reusableBuffer.viewText.filename[sizeof(MODELS_PATH)], g_eeGeneral.currModel); strcpy(buf, TEXT_EXT); waitKeysReleased(); @@ -126,13 +52,11 @@ void readModelNotes() void menuTextView(event_t event) { - static int lines_count; - switch (event) { case EVT_ENTRY: menuVerticalOffset = 0; - lines_count = 0; - readTextFile(lines_count); + reusableBuffer.viewText.linesCount = 0; + sdReadTextFile(reusableBuffer.viewText.filename, reusableBuffer.viewText.lines, reusableBuffer.viewText.linesCount); break; case EVT_KEY_PREVIOUS_LINE: @@ -140,15 +64,15 @@ void menuTextView(event_t event) break; else menuVerticalOffset--; - readTextFile(lines_count); + sdReadTextFile(reusableBuffer.viewText.filename, reusableBuffer.viewText.lines, reusableBuffer.viewText.linesCount); break; case EVT_KEY_NEXT_LINE: - if (menuVerticalOffset+LCD_LINES-1 >= lines_count) + if (menuVerticalOffset+LCD_LINES-1 >= reusableBuffer.viewText.linesCount) break; else ++menuVerticalOffset; - readTextFile(lines_count); + sdReadTextFile(reusableBuffer.viewText.filename, reusableBuffer.viewText.lines, reusableBuffer.viewText.linesCount); break; case EVT_KEY_BREAK(KEY_EXIT): @@ -157,10 +81,10 @@ void menuTextView(event_t event) } for (int i=0; i LCD_LINES-1) { - drawVerticalScrollbar(LCD_W-1, FH, LCD_H-FH, menuVerticalOffset, lines_count, LCD_LINES-1); + if (reusableBuffer.viewText.linesCount > LCD_LINES-1) { + drawVerticalScrollbar(LCD_W-1, FH, LCD_H-FH, menuVerticalOffset, reusableBuffer.viewText.linesCount, LCD_LINES-1); } } void pushMenuTextView(const char *filename) { if (strlen(filename) < TEXT_FILENAME_MAXLEN) { - strcpy(s_text_file, filename); + strcpy(reusableBuffer.viewText.filename, filename); pushMenu(menuTextView); } } diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h index 206508a96..50b282a59 100644 --- a/radio/src/gui/gui_common.h +++ b/radio/src/gui/gui_common.h @@ -27,6 +27,7 @@ #define READONLY_ROW ((uint8_t)-1) #define TITLE_ROW READONLY_ROW +#define LABEL(...) READONLY_ROW #define HIDDEN_ROW ((uint8_t)-2) #if defined(ROTARY_ENCODER_NAVIGATION) diff --git a/radio/src/keys.cpp b/radio/src/keys.cpp index 0fc7999dc..7514f3549 100644 --- a/radio/src/keys.cpp +++ b/radio/src/keys.cpp @@ -39,7 +39,7 @@ event_t s_evt; -struct t_inactivity inactivity = {0}; +struct InactivityData inactivity = {0}; Key keys[NUM_KEYS]; event_t getEvent(bool trim) diff --git a/radio/src/main.cpp b/radio/src/main.cpp index fb65851f3..a625327b7 100644 --- a/radio/src/main.cpp +++ b/radio/src/main.cpp @@ -490,24 +490,23 @@ void perMain() event_t evt = getEvent(false); #if defined(RAMBACKUP) - if (unexpectedShutdown) { + if (globalData.unexpectedShutdown) { drawFatalErrorScreen(STR_EMERGENCY_MODE); return; } #endif #if defined(STM32) - static bool sdcard_present_before = SD_CARD_PRESENT(); - bool sdcard_present_now = SD_CARD_PRESENT(); - if (sdcard_present_now && !sdcard_present_before) { + bool sdcardPresent = SD_CARD_PRESENT(); + if (sdcardPresent && !globalData.sdcardPresent) { sdMount(); } - sdcard_present_before = sdcard_present_now; + globalData.sdcardPresent = sdcardPresent; #endif #if !defined(EEPROM) // In case the SD card is removed during the session - if (!SD_CARD_PRESENT() && !unexpectedShutdown) { + if (!SD_CARD_PRESENT() && !globalData.unexpectedShutdown) { drawFatalErrorScreen(STR_NO_SDCARD); return; } diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 02a156356..ee8be104e 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -28,13 +28,9 @@ ModelData g_model; Clipboard clipboard; #endif -uint8_t unexpectedShutdown = 0; - -uint16_t vbattRTC; - -/* ARM: mixer duration in 0.5us */ -uint16_t maxMixerDuration; +GlobalData globalData; +uint16_t maxMixerDuration; // step = 0.01ms uint8_t heartbeat; #if defined(OVERRIDE_CHANNEL_FUNCTION) @@ -672,11 +668,6 @@ getvalue_t convert16bitsTelemValue(source_t channel, ls_telemetry_value_t value) return value; } -ls_telemetry_value_t minTelemValue(source_t channel) -{ - return 0; -} - ls_telemetry_value_t maxTelemValue(source_t channel) { return 30000; @@ -1841,12 +1832,14 @@ void opentxInit() // * radios without CPU controlled power can only use Reset status register (if available) if (UNEXPECTED_SHUTDOWN()) { TRACE("Unexpected Shutdown detected"); - unexpectedShutdown = 1; + globalData.unexpectedShutdown = 1; } #if defined(SDCARD) + globalData.sdcardPresent = SD_CARD_PRESENT(); + // SDCARD related stuff, only done if not unexpectedShutdown - if (!unexpectedShutdown) { + if (!globalData.unexpectedShutdown) { sdInit(); #if defined(AUTOUPDATE) @@ -1882,7 +1875,7 @@ void opentxInit() #endif #if defined(COLORLCD) - if (!unexpectedShutdown) { + if (!globalData.unexpectedShutdown) { // g_model.topbarData is still zero here (because it was not yet read from SDCARD), // but we only remember the pointer to in in constructor. // The storageReadAll() needs topbar object, so it must be created here @@ -1896,7 +1889,7 @@ void opentxInit() // handling of storage for radios that have no EEPROM #if !defined(EEPROM) #if defined(RAMBACKUP) - if (unexpectedShutdown) { + if (globalData.unexpectedShutdown) { // SDCARD not available, try to restore last model from RAM TRACE("rambackupRestore"); rambackupRestore(); @@ -1952,7 +1945,7 @@ void opentxInit() backlightOn(); } - if (!unexpectedShutdown) { + if (!globalData.unexpectedShutdown) { opentxStart(); } diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 984cf05f8..4046f7094 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -30,7 +30,6 @@ #include "opentx_types.h" #include "debounce.h" - #if defined(SIMU) #include "targets/simu/simpgmspace.h" #endif @@ -413,13 +412,13 @@ void watchdogSuspend(uint32_t timeout); #define MAX_ALERT_TIME 60 -struct t_inactivity +struct InactivityData { uint16_t counter; uint8_t sum; }; -extern struct t_inactivity inactivity; +extern InactivityData inactivity; #define LEN_STD_CHARS 40 @@ -566,9 +565,13 @@ extern uint8_t trimsDisplayMask; void flightReset(uint8_t check=true); -extern uint8_t unexpectedShutdown; +PACK(struct GlobalData { + uint8_t unexpectedShutdown:1; + uint8_t sdcardPresent:1; + uint8_t spare:6; +}); -extern uint16_t vbattRTC; +extern GlobalData globalData; extern uint16_t maxMixerDuration; @@ -1075,15 +1078,17 @@ constexpr uint8_t OPENTX_START_NO_CHECKS = 0x04; // Re-useable byte array to save having multiple buffers #if LCD_W <= 212 -#define SD_SCREEN_FILE_LENGTH 32 +constexpr uint8_t SD_SCREEN_FILE_LENGTH = 32; #else -#define SD_SCREEN_FILE_LENGTH 64 +constexpr uint8_t SD_SCREEN_FILE_LENGTH = 64; #endif #if defined(BLUETOOTH) #include "bluetooth.h" #endif +constexpr uint8_t TEXT_FILENAME_MAXLEN = 40; + union ReusableBuffer { struct { @@ -1199,13 +1204,29 @@ union ReusableBuffer int8_t preset; } curveEdit; + struct { + char filename[TEXT_FILENAME_MAXLEN]; + char lines[NUM_BODY_LINES][LCD_COLS + 1]; + int linesCount; + } viewText; + + struct { + bool longNames; + bool secondPage; + bool mixersView; + } viewChannels; + + struct { + uint8_t maxNameLen; + } modelFailsafe; + #if defined(STM32) // Data for the USB mass storage driver. If USB mass storage runs no menu is not allowed to be displayed uint8_t MSC_BOT_Data[MSC_MEDIA_PACKET]; #endif }; -extern union ReusableBuffer reusableBuffer; +extern ReusableBuffer reusableBuffer; uint8_t zlen(const char *str, uint8_t size); bool zexist(const char *str, uint8_t size); @@ -1224,13 +1245,15 @@ char * strcat_zchar(char *dest, const char *name, uint8_t size, const char *defa // Stick tolerance varies between transmitters, Higher is better #define STICK_TOLERANCE 64 - ls_telemetry_value_t minTelemValue(source_t channel); - ls_telemetry_value_t maxTelemValue(source_t channel); +ls_telemetry_value_t maxTelemValue(source_t channel); getvalue_t convert16bitsTelemValue(source_t channel, ls_telemetry_value_t value); getvalue_t convertLswTelemValue(LogicalSwitchData * cs); -#define convertTelemValue(channel, value) convert16bitsTelemValue(channel, value) +inline getvalue_t convertTelemValue(source_t channel, ls_telemetry_value_t value) +{ + return convert16bitsTelemValue(channel, value); +} inline int div_and_round(int num, int den) { @@ -1270,8 +1293,6 @@ extern uint8_t s_frsky_view; constexpr uint32_t EARTH_RADIUS = 6371009; -void getGpsPilotPosition(); -void getGpsDistance(); void varioWakeup(); #if defined(AUDIO) && defined(BUZZER) @@ -1356,15 +1377,6 @@ enum JackMode { #include "gyro.h" #endif -inline bool isSimu() -{ -#if defined(SIMU) - return true; -#else - return false; -#endif -} - #if defined(DEBUG_LATENCY) extern uint8_t latencyToggleSwitch; #endif @@ -1375,7 +1387,7 @@ inline bool isAsteriskDisplayed() return true; #endif - return unexpectedShutdown; + return globalData.unexpectedShutdown; } #endif // _OPENTX_H_ diff --git a/radio/src/pulses/pulses.h b/radio/src/pulses/pulses.h index 87208e7b9..a8ac93869 100644 --- a/radio/src/pulses/pulses.h +++ b/radio/src/pulses/pulses.h @@ -140,7 +140,7 @@ class BindInformation { class OtaUpdateInformation: public BindInformation { public: - char filename[_MAX_LFN+1]; + char filename[32+1]; uint32_t address; }; diff --git a/radio/src/sdcard.cpp b/radio/src/sdcard.cpp index 56705b633..3a16fde9f 100644 --- a/radio/src/sdcard.cpp +++ b/radio/src/sdcard.cpp @@ -410,6 +410,74 @@ bool sdListFiles(const char * path, const char * extension, const uint8_t maxlen return popupMenuItemsCount; } +constexpr uint32_t TEXT_FILE_MAXSIZE = 2048; + +void sdReadTextFile(const char * filename, char lines[NUM_BODY_LINES][LCD_COLS + 1], int & lines_count) +{ + FIL file; + int result; + char c; + unsigned int sz; + int line_length = 0; + uint8_t escape = 0; + char escape_chars[4] = {0}; + int current_line = 0; + + memclear(lines, NUM_BODY_LINES * (LCD_COLS + 1)); + + result = f_open(&file, filename, FA_OPEN_EXISTING | FA_READ); + if (result == FR_OK) { + for (unsigned i = 0; i < TEXT_FILE_MAXSIZE && f_read(&file, &c, 1, &sz) == FR_OK && sz == 1 && (lines_count == 0 || current_line - menuVerticalOffset < NUM_BODY_LINES); i++) { + if (c == '\n') { + ++current_line; + line_length = 0; + escape = 0; + } + else if (c!='\r' && current_line>=menuVerticalOffset && current_line-menuVerticalOffset 0 && escape < sizeof(escape_chars)) { + escape_chars[escape - 1] = c; + if (escape == 2 && !strncmp(escape_chars, "up", 2)) { + c = '\300'; + } + else if (escape == 2 && !strncmp(escape_chars, "dn", 2)) { + c = '\301'; + } + else if (escape == 3) { + int val = atoi(escape_chars); + if (val >= 200 && val < 225) { + c = '\200' + val-200; + } + } + else { + escape++; + continue; + } + } + else if (c=='~') { + c = 'z'+1; + } + else if (c=='\t') { + c = 0x1D; //tab + } + escape = 0; + lines[current_line-menuVerticalOffset][line_length++] = c; + } + } + if (c != '\n') { + current_line += 1; + } + f_close(&file); + } + + if (lines_count == 0) { + lines_count = current_line; + } +} + // returns true if current working dir is at the root level bool isCwdAtRoot() { diff --git a/radio/src/sdcard.h b/radio/src/sdcard.h index d56c9f7bd..e44c8508a 100644 --- a/radio/src/sdcard.h +++ b/radio/src/sdcard.h @@ -156,6 +156,8 @@ const char * sdCopyFile(const char * srcFilename, const char * srcDir, const cha #define LIST_SD_FILE_EXT 2 bool sdListFiles(const char * path, const char * extension, const uint8_t maxlen, const char * selection, uint8_t flags=0); +void sdReadTextFile(const char * filename, char lines[NUM_BODY_LINES][LCD_COLS + 1], int & lines_count); + bool isCwdAtRoot(); FRESULT sdReadDir(DIR * dir, FILINFO * fno, bool & firstTime); diff --git a/radio/src/switches.cpp b/radio/src/switches.cpp index 8e62a3212..f10bc9497 100644 --- a/radio/src/switches.cpp +++ b/radio/src/switches.cpp @@ -40,22 +40,21 @@ enum LogicalSwitchContextState { SWITCH_ENABLE }; -PACK(typedef struct { +PACK(struct LogicalSwitchContext { uint8_t state:1; uint8_t timerState:2; uint8_t spare:5; uint8_t timer; int16_t lastValue; -}) LogicalSwitchContext; +}); -PACK(typedef struct { +PACK(struct LogicalSwitchesFlightModeContext { LogicalSwitchContext lsw[MAX_LOGICAL_SWITCHES]; -}) LogicalSwitchesFlightModeContext; +}); LogicalSwitchesFlightModeContext lswFm[MAX_FLIGHT_MODES]; #define LS_LAST_VALUE(fm, idx) lswFm[fm].lsw[idx].lastValue - #if defined(PCBTARANIS) || defined(PCBHORUS) #if defined(PCBX9E) tmr10ms_t switchesMidposStart[16]; diff --git a/radio/src/targets/horus/board.h b/radio/src/targets/horus/board.h index ff4618b87..8aae48224 100644 --- a/radio/src/targets/horus/board.h +++ b/radio/src/targets/horus/board.h @@ -510,8 +510,8 @@ void backlightEnable(uint8_t dutyCycle = 0); #else #define BACKLIGHT_LEVEL_MIN 46 #endif -#define BACKLIGHT_ENABLE() backlightEnable(unexpectedShutdown ? BACKLIGHT_LEVEL_MAX : BACKLIGHT_LEVEL_MAX-g_eeGeneral.backlightBright) -#define BACKLIGHT_DISABLE() backlightEnable(unexpectedShutdown ? BACKLIGHT_LEVEL_MAX : ((g_eeGeneral.blOffBright == BACKLIGHT_LEVEL_MIN) && (g_eeGeneral.backlightMode != e_backlight_mode_off)) ? 0 : g_eeGeneral.blOffBright) +#define BACKLIGHT_ENABLE() backlightEnable(globalData.unexpectedShutdown ? BACKLIGHT_LEVEL_MAX : BACKLIGHT_LEVEL_MAX-g_eeGeneral.backlightBright) +#define BACKLIGHT_DISABLE() backlightEnable(globalData.unexpectedShutdown ? BACKLIGHT_LEVEL_MAX : ((g_eeGeneral.blOffBright == BACKLIGHT_LEVEL_MIN) && (g_eeGeneral.backlightMode != e_backlight_mode_off)) ? 0 : g_eeGeneral.blOffBright) #define isBacklightEnabled() true #if !defined(SIMU) diff --git a/radio/src/targets/sky9x/lcd_driver.cpp b/radio/src/targets/sky9x/lcd_driver.cpp index 31e1d12d1..d8453ebe1 100644 --- a/radio/src/targets/sky9x/lcd_driver.cpp +++ b/radio/src/targets/sky9x/lcd_driver.cpp @@ -115,7 +115,7 @@ void lcdInit() #if defined(REVX) // 200mS delay (only if not wdt reset) - if ( ( ( ResetReason & RSTC_SR_RSTTYP ) != (2 << 8) ) && !unexpectedShutdown ) { + if ( ( ( ResetReason & RSTC_SR_RSTTYP ) != (2 << 8) ) && !globalData.unexpectedShutdown ) { for (uint32_t j = 0; j < 100; j += 1 ) { TC0->TC_CHANNEL[0].TC_CCR = 5; // Enable clock and trigger it (may only need trigger) while ( TC0->TC_CHANNEL[0].TC_CV < 36000 ) { diff --git a/radio/src/targets/taranis/trainer_driver.cpp b/radio/src/targets/taranis/trainer_driver.cpp index 0e95f2a59..06a006899 100644 --- a/radio/src/targets/taranis/trainer_driver.cpp +++ b/radio/src/targets/taranis/trainer_driver.cpp @@ -329,15 +329,12 @@ void stop_trainer_module_sbus() } #endif -uint32_t ccount = 0; - #if defined(SBUS) int sbusGetByte(uint8_t * byte) { switch (currentTrainerMode) { #if defined(TRAINER_MODULE_SBUS_USART) case TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE: - ccount++; return trainerSbusFifo.pop(*byte); #endif #if defined(AUX_SERIAL_USART) diff --git a/radio/src/tasks.h b/radio/src/tasks.h index 26b913f72..921958363 100644 --- a/radio/src/tasks.h +++ b/radio/src/tasks.h @@ -18,15 +18,15 @@ * GNU General Public License for more details. */ -#ifndef _TASKS_ARM_H_ -#define _TASKS_ARM_H_ +#ifndef _TASKS_H_ +#define _TASKS_H_ #include "rtos.h" // stack sizes should be in multiples of 8 for better alignment #define MENUS_STACK_SIZE 2000 -#define MIXER_STACK_SIZE 512 -#define AUDIO_STACK_SIZE 512 +#define MIXER_STACK_SIZE 400 +#define AUDIO_STACK_SIZE 400 #define CLI_STACK_SIZE 1000 // only consumed with CLI build option #define MIXER_TASK_PRIO 5 @@ -55,4 +55,4 @@ inline void resetForcePowerOffRequest() timeForcePowerOffPressed = 0; } -#endif // _TASKS_ARM_H_ +#endif // _TASKS_H_ diff --git a/radio/src/telemetry/telemetry.cpp b/radio/src/telemetry/telemetry.cpp index ac3a38a5b..71845ef53 100644 --- a/radio/src/telemetry/telemetry.cpp +++ b/radio/src/telemetry/telemetry.cpp @@ -21,14 +21,9 @@ #include "opentx.h" uint8_t telemetryStreaming = 0; -uint8_t R9ModuleStreaming = 0; uint8_t telemetryRxBuffer[TELEMETRY_RX_PACKET_SIZE]; // Receive buffer. 9 bytes (full packet), worst case 18 bytes with byte-stuffing (+1) uint8_t telemetryRxBufferCount = 0; -#if defined(WS_HOW_HIGH) -uint8_t wshhStreaming = 0; -#endif - uint8_t telemetryState = TELEMETRY_INIT; TelemetryData telemetryData; @@ -210,7 +205,6 @@ void telemetryWakeup() void telemetryInterrupt10ms() { - if (TELEMETRY_STREAMING()) { for (int i=0; i 0) { - wshhStreaming--; - } -#endif - if (R9ModuleStreaming > 0) { - R9ModuleStreaming--; - } if (telemetryStreaming > 0) { telemetryStreaming--; } diff --git a/radio/src/telemetry/telemetry.h b/radio/src/telemetry/telemetry.h index d2f6dadc7..56caf35db 100644 --- a/radio/src/telemetry/telemetry.h +++ b/radio/src/telemetry/telemetry.h @@ -30,11 +30,6 @@ #endif extern uint8_t telemetryStreaming; // >0 (true) == data is streaming in. 0 = no data detected for some time -extern uint8_t R9ModuleStreaming; // >0 (true) == R9 module is connected and sending data 0 = no data detected for some time - -#if defined(WS_HOW_HIGH) -extern uint8_t wshhStreaming; -#endif enum TelemetryStates { TELEMETRY_INIT, diff --git a/tools/extract-map.py b/tools/extract-map.py new file mode 100755 index 000000000..95e87ebce --- /dev/null +++ b/tools/extract-map.py @@ -0,0 +1,48 @@ +#!/usr/bin/python3 + +import argparse + + +def line_index(lines, start): + for i, line in enumerate(lines): + if line.startswith(start): + return i + + +def extract_vars(lines): + result = [] + lines = lines[line_index(lines, ".data"):line_index(lines, ".memory")] + i = 0 + while i < len(lines): + line = lines[i] + i += 1 + if line.startswith("*"): + continue + if line.startswith(" .data.") or line.startswith(" .bss."): + fields = (line + lines[i]).split() + # print(fields) + i += 1 + var = fields[0].split(".")[-1] + offset = int(fields[1], 16) + size = int(fields[2], 16) + result.append((var, offset, size)) + return result + + +def main(): + parser = argparse.ArgumentParser(description="Extract firmware.map") + parser.add_argument("file", type=argparse.FileType("r")) + + args = parser.parse_args() + + f = args.file + lines = f.readlines() + + vars = extract_vars(lines) + vars.sort(key=lambda var: "%08d %s" % (var[2], var[0])) + for var, offset, size in vars: + print("%s\t %d" % (var, size)) + + +if __name__ == "__main__": + main()