diff --git a/radio/src/gui/Taranis/menu_general_sdmanager.cpp b/radio/src/gui/Taranis/menu_general_sdmanager.cpp index a26884c74..2fd67aa1d 100755 --- a/radio/src/gui/Taranis/menu_general_sdmanager.cpp +++ b/radio/src/gui/Taranis/menu_general_sdmanager.cpp @@ -36,6 +36,8 @@ #include "../../opentx.h" +#define REFRESH_FILES() reusableBuffer.sdmanager.offset = 65535 + void menuGeneralSdManagerInfo(uint8_t event) { SIMPLE_SUBMENU(STR_SD_INFO_TITLE, 1); @@ -116,60 +118,85 @@ void onSdManagerMenu(const char *result) { TCHAR lfn[_MAX_LFN+1]; + // TODO possible buffer overflows here! + uint8_t index = m_posVert-1-s_pgOfs; + char *line = reusableBuffer.sdmanager.lines[index]; + if (result == STR_SD_INFO) { pushMenu(menuGeneralSdManagerInfo); } else if (result == STR_SD_FORMAT) { POPUP_CONFIRMATION(STR_CONFIRM_FORMAT); } + else if (result == STR_COPY_FILE) { + clipboard.type = CLIPBOARD_TYPE_SD_FILE; + f_getcwd(clipboard.data.sd.directory, CLIPBOARD_PATH_LEN); + strncpy(clipboard.data.sd.filename, line, CLIPBOARD_PATH_LEN-1); + } + else if (result == STR_PASTE) { + f_getcwd(lfn, _MAX_LFN); + POPUP_WARNING(fileCopy(clipboard.data.sd.filename, clipboard.data.sd.directory, lfn)); + REFRESH_FILES(); + } + else if (result == STR_RENAME_FILE) { + char *ext = getFileExtension(line, SD_SCREEN_FILE_LENGTH+1); + if (ext) { + memcpy(reusableBuffer.sdmanager.originalName, line, sizeof(reusableBuffer.sdmanager.originalName)); + // write spaces to allow a longer filename + memset(ext, ' ', SD_SCREEN_FILE_LENGTH-LEN_FILE_EXTENSION-(ext-line)); + line[SD_SCREEN_FILE_LENGTH-LEN_FILE_EXTENSION] = '\0'; + s_editMode = EDIT_MODIFY_STRING; + editNameCursorPos = 0; + } + } else if (result == STR_DELETE_FILE) { f_getcwd(lfn, _MAX_LFN); - strcat_P(lfn, PSTR("/")); - strcat(lfn, reusableBuffer.sdmanager.lines[index]); + strcat(lfn, PSTR("/")); + strcat(lfn, line); f_unlink(lfn); - strncpy(statusLineMsg, reusableBuffer.sdmanager.lines[index], 13); + strncpy(statusLineMsg, line, 13); strcpy_P(statusLineMsg+min((uint8_t)strlen(statusLineMsg), (uint8_t)13), STR_REMOVED); showStatusLine(); - if ((uint16_t)m_posVert == reusableBuffer.sdmanager.count) m_posVert--; - reusableBuffer.sdmanager.offset = s_pgOfs-1; + REFRESH_FILES(); + if (m_posVert == reusableBuffer.sdmanager.count) + m_posVert--; } /* TODO else if (result == STR_LOAD_FILE) { f_getcwd(lfn, _MAX_LFN); strcat(lfn, "/"); - strcat(lfn, reusableBuffer.sdmanager.lines[index]); + strcat(lfn, line); POPUP_WARNING(eeLoadModelSD(lfn)); } */ else if (result == STR_PLAY_FILE) { f_getcwd(lfn, _MAX_LFN); strcat(lfn, "/"); - strcat(lfn, reusableBuffer.sdmanager.lines[index]); + strcat(lfn, line); audioQueue.stopAll(); audioQueue.playFile(lfn, 0, ID_PLAY_FROM_SD_MANAGER); } else if (result == STR_ASSIGN_BITMAP) { - strAppendFilename(g_model.header.bitmap, reusableBuffer.sdmanager.lines[index], sizeof(g_model.header.bitmap)); - LOAD_MODEL_BITMAP(); + strAppendFilename(g_model.header.bitmap, line, sizeof(g_model.header.bitmap)); memcpy(modelHeaders[g_eeGeneral.currModel].bitmap, g_model.header.bitmap, sizeof(g_model.header.bitmap)); eeDirty(EE_MODEL); } else if (result == STR_VIEW_TEXT) { f_getcwd(lfn, _MAX_LFN); strcat(lfn, "/"); - strcat(lfn, reusableBuffer.sdmanager.lines[index]); + strcat(lfn, line); pushMenuTextView(lfn); } else if (result == STR_FLASH_BOOTLOADER) { f_getcwd(lfn, _MAX_LFN); strcat(lfn, "/"); - strcat(lfn, reusableBuffer.sdmanager.lines[index]); + strcat(lfn, line); flashBootloader(lfn); } #if defined(LUA) else if (result == STR_EXECUTE_FILE) { f_getcwd(lfn, _MAX_LFN); strcat(lfn, "/"); - strcat(lfn, reusableBuffer.sdmanager.lines[index]); + strcat(lfn, line); luaExec(lfn); } #endif @@ -191,27 +218,28 @@ void menuGeneralSdManager(uint8_t _event) audioQueue.stopSD(); if (f_mkfs(0, 1, 0) == FR_OK) { f_chdir("/"); - reusableBuffer.sdmanager.offset = -1; + REFRESH_FILES(); } else { POPUP_WARNING(STR_SDCARD_ERROR); } } - uint8_t event = ((READ_ONLY() && EVT_KEY_MASK(_event) == KEY_ENTER) ? 0 : _event); + int lastPos = m_posVert; + + uint8_t event = (EVT_KEY_MASK(_event) == KEY_ENTER ? 0 : _event); SIMPLE_MENU(SD_IS_HC() ? STR_SDHC_CARD : STR_SD_CARD, menuTabGeneral, e_Sd, 1+reusableBuffer.sdmanager.count); - if (s_editMode > 0) - s_editMode = 0; + int index = m_posVert-1-s_pgOfs; switch(_event) { case EVT_ENTRY: f_chdir(ROOT_PATH); - reusableBuffer.sdmanager.offset = 65535; + REFRESH_FILES(); break; case EVT_KEY_LONG(KEY_MENU): - if (!READ_ONLY()) { + if (!READ_ONLY() && s_editMode == 0) { killEvents(_event); // MENU_ADD_ITEM(STR_SD_INFO); TODO: Implement MENU_ADD_ITEM(STR_SD_FORMAT); @@ -219,32 +247,35 @@ void menuGeneralSdManager(uint8_t _event) } break; + case EVT_KEY_BREAK(KEY_EXIT): + REFRESH_FILES(); + break; + case EVT_KEY_BREAK(KEY_ENTER): - { - if (m_posVert > 0) { - vertpos_t index = m_posVert-1-s_pgOfs; - if (!reusableBuffer.sdmanager.lines[index][SD_SCREEN_FILE_LENGTH+1]) { - f_chdir(reusableBuffer.sdmanager.lines[index]); - s_pgOfs = 0; - m_posVert = 1; - reusableBuffer.sdmanager.offset = 65535; - killEvents(_event); - break; + if (s_editMode > 0) { + break; + } + else { + if (m_posVert > 0) { + if (!reusableBuffer.sdmanager.lines[index][SD_SCREEN_FILE_LENGTH+1]) { + f_chdir(reusableBuffer.sdmanager.lines[index]); + s_pgOfs = 0; + m_posVert = 1; + index = 1; + REFRESH_FILES(); + killEvents(_event); + return; + } } } - if (!IS_ROTARY_BREAK(_event) || m_posVert==0) - break; - // no break; - } + // no break case EVT_KEY_LONG(KEY_ENTER): killEvents(_event); - { - uint8_t index = m_posVert-1-s_pgOfs; - // TODO duplicated code for finding extension - char * ext = reusableBuffer.sdmanager.lines[index]; - int len = strlen(ext) - 4; - ext += len; + if (s_editMode == 0) { + char *line = reusableBuffer.sdmanager.lines[index]; + char *ext = getFileExtension(line, SD_SCREEN_FILE_LENGTH+1); + int len = ext - line; /* TODO if (!strcasecmp(ext, MODELS_EXT)) { s_menu[s_menu_count++] = STR_LOAD_FILE; } @@ -266,9 +297,12 @@ void menuGeneralSdManager(uint8_t _event) } #endif if (!READ_ONLY()) { + if (line[SD_SCREEN_FILE_LENGTH+1]) // it's a file + MENU_ADD_ITEM(STR_COPY_FILE); + if (clipboard.type == CLIPBOARD_TYPE_SD_FILE) + MENU_ADD_ITEM(STR_PASTE); + MENU_ADD_ITEM(STR_RENAME_FILE); MENU_ADD_ITEM(STR_DELETE_FILE); - // MENU_ADD_ITEM(STR_RENAME_FILE); TODO: Implement - // MENU_ADD_ITEM(STR_COPY_FILE); TODO: Implement } } menuHandler = onSdManagerMenu; @@ -360,29 +394,32 @@ void menuGeneralSdManager(uint8_t _event) for (uint8_t i=0; i 0) { - char * ext = reusableBuffer.sdmanager.lines[index]; - ext += strlen(ext) - 4; - if (!strcasecmp(ext, BITMAPS_EXT)) { - if (sdBitmapIdx != m_posVert) { - sdBitmapIdx = m_posVert; - uint8_t *dest = sdBitmap; - if (bmpLoad(dest, reusableBuffer.sdmanager.lines[index], MODEL_BITMAP_WIDTH, MODEL_BITMAP_HEIGHT)) { - memcpy(sdBitmap, logo_taranis, MODEL_BITMAP_SIZE); - } + char *ext = getFileExtension(reusableBuffer.sdmanager.lines[index], SD_SCREEN_FILE_LENGTH+1); + if (ext && !strcasecmp(ext, BITMAPS_EXT)) { + if (lastPos != m_posVert) { + if (bmpLoad(modelBitmap, reusableBuffer.sdmanager.lines[index], MODEL_BITMAP_WIDTH, MODEL_BITMAP_HEIGHT)) { + memcpy(modelBitmap, logo_taranis, MODEL_BITMAP_SIZE); } - lcd_bmp(22*FW+2, 2*FH+FH/2, sdBitmap); } + lcd_bmp(22*FW+2, 2*FH+FH/2, modelBitmap); } } diff --git a/radio/src/gui/Taranis/menu_model.cpp b/radio/src/gui/Taranis/menu_model.cpp index 627eeaf27..96ef596fc 100755 --- a/radio/src/gui/Taranis/menu_model.cpp +++ b/radio/src/gui/Taranis/menu_model.cpp @@ -138,7 +138,7 @@ static int8_t s_copyTgtOfs; static uint8_t editNameCursorPos = 0; -void editName(coord_t x, coord_t y, char *name, uint8_t size, uint8_t event, uint8_t active) +void editName(coord_t x, coord_t y, char *name, uint8_t size, uint8_t event, uint8_t active, uint8_t attr) { uint8_t mode = 0; if (active) { @@ -148,7 +148,7 @@ void editName(coord_t x, coord_t y, char *name, uint8_t size, uint8_t event, uin mode = FIXEDWIDTH; } - lcd_putsnAtt(x, y, name, size, ZCHAR | mode); + lcd_putsnAtt(x, y, name, size, attr | mode); if (active) { uint8_t cur = editNameCursorPos; @@ -158,8 +158,14 @@ void editName(coord_t x, coord_t y, char *name, uint8_t size, uint8_t event, uin if (IS_ROTARY_RIGHT(event) || IS_ROTARY_LEFT(event) || event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_FIRST(KEY_UP) || event==EVT_KEY_REPT(KEY_DOWN) || event==EVT_KEY_REPT(KEY_UP)) { - v = checkIncDec(event, abs(v), 0, ZCHAR_MAX, 0); - if (c <= 0) v = -v; + if (attr == ZCHAR) { + v = checkIncDec(event, abs(v), 0, ZCHAR_MAX, 0); + if (c <= 0) v = -v; + } + else { + v = checkIncDec(event, abs(v), '0', 'z', 0); + } + } switch (event) { @@ -175,7 +181,7 @@ void editName(coord_t x, coord_t y, char *name, uint8_t size, uint8_t event, uin break; case EVT_ROTARY_LONG: - if (v==0) { + if ((attr == ZCHAR && v==0) || (attr == 0 && v==' ')) { s_editMode = 0; killEvents(event); break; @@ -193,7 +199,12 @@ void editName(coord_t x, coord_t y, char *name, uint8_t size, uint8_t event, uin eeDirty(g_menuPos[0] == 0 ? EE_MODEL : EE_GENERAL); } - lcd_putcAtt(x+editNameCursorPos*FW, y, idx2char(v), ERASEBG|INVERS|FIXEDWIDTH); + if (attr == ZCHAR) { + lcd_putcAtt(x+editNameCursorPos*FW, y, idx2char(v), ERASEBG|INVERS|FIXEDWIDTH); + } + else { + lcd_putcAtt(x+editNameCursorPos*FW, y, v, ERASEBG|INVERS|FIXEDWIDTH); + } } else { cur = 0; diff --git a/radio/src/gui/Taranis/menu_model_logical_switches.cpp b/radio/src/gui/Taranis/menu_model_logical_switches.cpp index e66644e5d..256557a2d 100755 --- a/radio/src/gui/Taranis/menu_model_logical_switches.cpp +++ b/radio/src/gui/Taranis/menu_model_logical_switches.cpp @@ -73,22 +73,6 @@ void putsEdgeDelayParam(coord_t x, coord_t y, LogicalSwitchData *cs, uint8_t lat lcd_putc(lcdLastPos, y, ']'); } -enum ClipboardType { - CLIPBOARD_TYPE_NONE, - CLIPBOARD_TYPE_CUSTOM_SWITCH, - CLIPBOARD_TYPE_CUSTOM_FUNCTION, -}; - -struct Clipboard { - ClipboardType type; - union { - LogicalSwitchData csw; - CustomFunctionData cfn; - } data; -}; - -Clipboard clipboard; - void onLogicalSwitchesMenu(const char *result) { int8_t sub = m_posVert-1; diff --git a/radio/src/gui/Taranis/menu_model_select.cpp b/radio/src/gui/Taranis/menu_model_select.cpp index c9bf9cc09..51db6f2cb 100644 --- a/radio/src/gui/Taranis/menu_model_select.cpp +++ b/radio/src/gui/Taranis/menu_model_select.cpp @@ -37,10 +37,7 @@ #define MODELSIZE_POS_X 170 -static int8_t modelselBitmapIdx; -static uint8_t modelselBitmap[MODEL_BITMAP_SIZE]; #define MODELSEL_W 133 -#define BMP_DIRTY() modelselBitmapIdx = -1 void onModelSelectMenu(const char *result) { @@ -76,7 +73,6 @@ void onModelSelectMenu(const char *result) else { // The user choosed a file on SD to restore POPUP_WARNING(eeRestoreModel(sub, (char *)result)); - BMP_DIRTY(); if (!s_warning && g_eeGeneral.currModel == sub) eeLoadModel(sub); } @@ -89,7 +85,6 @@ void menuModelSelect(uint8_t event) eeDeleteModel(m_posVert); // delete file s_copyMode = 0; event = EVT_ENTRY_UP; - BMP_DIRTY(); } uint8_t _event_ = (IS_ROTARY_BREAK(event) || IS_ROTARY_LONG(event) ? 0 : event); @@ -112,9 +107,9 @@ void menuModelSelect(uint8_t event) if (sub >= NUM_BODY_LINES) s_pgOfs = sub-(NUM_BODY_LINES-1); s_copyMode = 0; s_editMode = EDIT_MODE_INIT; - BMP_DIRTY(); eeCheck(true); break; + case EVT_KEY_LONG(KEY_EXIT): if (s_copyMode && s_copyTgtOfs == 0 && g_eeGeneral.currModel != sub && eeModelExists(sub)) { POPUP_CONFIRMATION(STR_DELETEMODEL); @@ -130,7 +125,7 @@ void menuModelSelect(uint8_t event) } else { if (m_posVert != g_eeGeneral.currModel) { - m_posVert = g_eeGeneral.currModel; + sub = m_posVert = g_eeGeneral.currModel; s_pgOfs = 0; } else if (event != EVT_KEY_LONG(KEY_EXIT)) { @@ -153,9 +148,7 @@ void menuModelSelect(uint8_t event) uint8_t cur = (MAX_MODELS + sub + s_copyTgtOfs) % MAX_MODELS; if (s_copyMode == COPY_MODE) { - if (eeCopyModel(cur, s_copySrcRow)) - BMP_DIRTY(); - else + if (!eeCopyModel(cur, s_copySrcRow)) cur = sub; } @@ -164,7 +157,6 @@ void menuModelSelect(uint8_t event) uint8_t src = cur; cur = (s_copyTgtOfs > 0 ? cur+MAX_MODELS-1 : cur+1) % MAX_MODELS; eeSwapModels(src, cur); - BMP_DIRTY(); if (src == s_copySrcRow) s_copySrcRow = cur; else if (cur == s_copySrcRow) @@ -289,12 +281,9 @@ void menuModelSelect(uint8_t event) } } - if (modelselBitmapIdx != m_posVert) { - modelselBitmapIdx = m_posVert; - if (modelselBitmapIdx == g_eeGeneral.currModel) - memcpy(modelselBitmap, modelBitmap, MODEL_BITMAP_SIZE); - else - loadModelBitmap(modelHeaders[sub].bitmap, modelselBitmap); + if (event == EVT_ENTRY || sub != oldSub) { + loadModelBitmap(modelHeaders[sub].bitmap, modelBitmap); } - lcd_bmp(22*FW+2, 2*FH+FH/2, modelselBitmap); + + lcd_bmp(22*FW+2, 2*FH+FH/2, modelBitmap); } diff --git a/radio/src/gui/Taranis/menu_model_setup.cpp b/radio/src/gui/Taranis/menu_model_setup.cpp index e06142645..0c9033e5b 100644 --- a/radio/src/gui/Taranis/menu_model_setup.cpp +++ b/radio/src/gui/Taranis/menu_model_setup.cpp @@ -115,7 +115,6 @@ void onModelSetupBitmapMenu(const char *result) else { // The user choosed a bmp file in the list copySelection(g_model.header.bitmap, result, sizeof(g_model.header.bitmap)); - LOAD_MODEL_BITMAP(); memcpy(modelHeaders[g_eeGeneral.currModel].bitmap, g_model.header.bitmap, sizeof(g_model.header.bitmap)); eeDirty(EE_MODEL); } diff --git a/radio/src/gui/Taranis/menus.h b/radio/src/gui/Taranis/menus.h index 38240260e..8afd5a87d 100755 --- a/radio/src/gui/Taranis/menus.h +++ b/radio/src/gui/Taranis/menus.h @@ -290,7 +290,7 @@ int8_t switchMenuItem(coord_t x, coord_t y, int8_t value, LcdFlags attr, uint8_t #define displayGVar(x, y, v, min, max) lcd_outdez8(x, y, v) #endif -void editName(coord_t x, coord_t y, char *name, uint8_t size, uint8_t event, uint8_t active); +void editName(coord_t x, coord_t y, char *name, uint8_t size, uint8_t event, uint8_t active, uint8_t attr=ZCHAR); #define WARNING_TYPE_ASTERISK 0 #define WARNING_TYPE_CONFIRM 1 diff --git a/radio/src/gui/Taranis/view_main.cpp b/radio/src/gui/Taranis/view_main.cpp index 46d9abf2f..64fad251a 100755 --- a/radio/src/gui/Taranis/view_main.cpp +++ b/radio/src/gui/Taranis/view_main.cpp @@ -441,6 +441,10 @@ void menuMainView(uint8_t event) killEvents(KEY_EXIT); killEvents(KEY_UP); killEvents(KEY_DOWN); + // no break + + case EVT_ENTRY_UP: + LOAD_MODEL_BITMAP(); break; case EVT_KEY_CONTEXT_MENU: diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 079dc9c77..9a4450a4f 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -50,6 +50,10 @@ EEGeneral g_eeGeneral; ModelData g_model; +#if defined(SDCARD) +Clipboard clipboard; +#endif + #if defined(PCBTARANIS) && defined(SDCARD) uint8_t modelBitmap[MODEL_BITMAP_SIZE]; void loadModelBitmap(char *name, uint8_t *bitmap) diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 201d638ad..2615f5d14 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -1513,6 +1513,7 @@ extern uint8_t requiredSpeakerVolume; #define SD_SCREEN_FILE_LENGTH (32) union ReusableBuffer { + // 275 bytes struct { char listnames[LCD_LINES-1][LEN_MODEL_NAME]; @@ -1526,6 +1527,7 @@ union ReusableBuffer } modelsel; + // 103 bytes struct { int16_t midVals[NUM_STICKS+NUM_POTS]; @@ -1543,12 +1545,14 @@ union ReusableBuffer } calib; #if defined(SDCARD) + // 274 bytes struct { char lines[LCD_LINES-1][SD_SCREEN_FILE_LENGTH+1+1]; // the last char is used to store the flags (directory) of the line uint32_t available; uint16_t offset; uint16_t count; + char originalName[SD_SCREEN_FILE_LENGTH+1]; } sdmanager; #endif }; @@ -1721,4 +1725,33 @@ void varioWakeup(); #include "lua_api.h" +#if defined(SDCARD) +enum ClipboardType { + CLIPBOARD_TYPE_NONE, + CLIPBOARD_TYPE_CUSTOM_SWITCH, + CLIPBOARD_TYPE_CUSTOM_FUNCTION, + CLIPBOARD_TYPE_SD_FILE, +}; + +#if defined(SIMU) + #define CLIPBOARD_PATH_LEN 1024 +#else + #define CLIPBOARD_PATH_LEN 32 +#endif + +struct Clipboard { + ClipboardType type; + union { + LogicalSwitchData csw; + CustomFunctionData cfn; + struct { + char directory[CLIPBOARD_PATH_LEN]; + char filename[CLIPBOARD_PATH_LEN]; + } sd; + } data; +}; + +extern Clipboard clipboard; +#endif + #endif diff --git a/radio/src/sdcard.cpp b/radio/src/sdcard.cpp index e8bb710cb..525386456 100644 --- a/radio/src/sdcard.cpp +++ b/radio/src/sdcard.cpp @@ -141,3 +141,48 @@ bool listSdFiles(const char *path, const char *extension, const uint8_t maxlen, return s_menu_count; } + +const char *fileCopy(const char *filename, const char *srcDir, const char *destDir) +{ + FIL srcFile; + FIL dstFile; + char buf[256]; + UINT read = sizeof(buf); + UINT written = sizeof(buf); + + char path[2*CLIPBOARD_PATH_LEN+1]; + char *tmp = strAppend(path, srcDir, CLIPBOARD_PATH_LEN); + *tmp++ = '/'; + strAppend(tmp, filename, CLIPBOARD_PATH_LEN); + + FRESULT result = f_open(&srcFile, path, FA_OPEN_EXISTING | FA_READ); + if (result != FR_OK) { + return SDCARD_ERROR(result); + } + + tmp = strAppend(path, destDir, CLIPBOARD_PATH_LEN); + *tmp++ = '/'; + strAppend(tmp, filename, CLIPBOARD_PATH_LEN); + + result = f_open(&dstFile, path, FA_CREATE_ALWAYS | FA_WRITE); + if (result != FR_OK) { + f_close(&srcFile); + return SDCARD_ERROR(result); + } + + while (result==FR_OK && read==sizeof(buf) && written==sizeof(buf)) { + result = f_read(&srcFile, buf, sizeof(buf), &read); + if (result == FR_OK) { + result = f_write(&dstFile, buf, read, &written); + } + } + + f_close(&dstFile); + f_close(&srcFile); + + if (result != FR_OK) { + return SDCARD_ERROR(result); + } + + return NULL; +} diff --git a/radio/src/sdcard.h b/radio/src/sdcard.h index 9a31be9c9..efe91da54 100644 --- a/radio/src/sdcard.h +++ b/radio/src/sdcard.h @@ -34,8 +34,8 @@ * */ -#ifndef sdcard_h -#define sdcard_h +#ifndef _SDCARD_H_ +#define _SDCARD_H_ #include "FatFs/ff.h" @@ -68,10 +68,10 @@ extern FATFS g_FATFS_Obj; extern uint8_t logDelay; -extern const pm_char * openLogs(); +const pm_char *openLogs(); void writeHeader(); -extern void closeLogs(); -extern void writeLogs(); +void closeLogs(); +void writeLogs(); #if !defined(BOOT) inline const pm_char *SDCARD_ERROR(FRESULT result) @@ -91,5 +91,7 @@ inline const pm_char *SDCARD_ERROR(FRESULT result) #define O9X_FOURCC 0x3178396F // o9x for gruvin9x/MEGA2560 #endif +const char *fileCopy(const char *filename, const char *srcDir, const char *destDir); + #endif diff --git a/radio/src/strhelpers.cpp b/radio/src/strhelpers.cpp index 856a67e7b..0d49fc9ac 100644 --- a/radio/src/strhelpers.cpp +++ b/radio/src/strhelpers.cpp @@ -97,6 +97,16 @@ int zchar2str(char *dest, const char *src, int size) #endif #if defined(CPUARM) +unsigned int effectiveLen(const char *str, unsigned int size) +{ + while (size > 0) { + if (str[size-1] != ' ') + return size; + size--; + } + return 0; +} + bool zexist(const char *str, uint8_t size) { for (int i=0; ifs) *written = fwrite(data, 1, size, (FILE*)fil->fs); + if (fil && fil->fs) { + *written = fwrite(data, 1, size, (FILE*)fil->fs); + // TRACE("fwrite(%p) %u, %u", fil->fs, size, *written); + } return FR_OK; } @@ -637,6 +640,11 @@ FRESULT f_unlink (const TCHAR*) return FR_OK; } +FRESULT f_rename(const TCHAR*, const TCHAR*) +{ + return FR_OK; +} + int f_putc (TCHAR c, FIL * fil) { if (fil && fil->fs) fwrite(&c, 1, 1, (FILE*)fil->fs); diff --git a/radio/util/font2png.py b/radio/util/font2png.py index f322dc0e5..a989ef377 100755 --- a/radio/util/font2png.py +++ b/radio/util/font2png.py @@ -37,9 +37,10 @@ def createFontBitmap(filename, foreground, background): if i == 0: rect.setWidth(4) elif i == 14: - rect.setLeft(rect.left()+1) rect.setWidth(1) - painter.drawText(width*i-rect.left(), size+1, c) + painter.drawPoint(width*i, size); + else: + painter.drawText(width*i-rect.left(), size+1, c) for j in range(rect.width(), width): painter.drawLine(width*i+j, 0, width*i+j, size+4) painter.end()