Improvements, more SORT_USES_MORE_RAM

With this option, always keeps the dir in RAM, doubling as a cache for
getfilename. A board with only 8K of SRAM is cutting it very close.
This commit is contained in:
Scott Lahteine 2014-11-26 07:17:47 -08:00
parent 87fc00c182
commit 6901445592
3 changed files with 78 additions and 81 deletions

View File

@ -11,8 +11,7 @@
CardReader::CardReader() CardReader::CardReader()
{ {
#if defined(SDCARD_SORT_ALPHA) && SORT_USES_MORE_RAM #ifdef SDCARD_SORT_ALPHA
sortnames = NULL;
sort_count = 0; sort_count = 0;
#endif #endif
filesize = 0; filesize = 0;
@ -40,13 +39,9 @@ CardReader::CardReader()
char *createFilename(char *buffer, const dir_t &p) //buffer>12characters char *createFilename(char *buffer, const dir_t &p) //buffer>12characters
{ {
char *pos=buffer; char *pos=buffer;
for (uint8_t i = 0; i < 11; i++) for (uint8_t i = 0; i < 11; i++) {
{
if (p.name[i] == ' ') continue; if (p.name[i] == ' ') continue;
if (i == 8) if (i == 8) *pos++ = '.';
{
*pos++='.';
}
*pos++ = p.name[i]; *pos++ = p.name[i];
} }
*pos++ = 0; *pos++ = 0;
@ -59,7 +54,7 @@ void CardReader::lsDive(const char *prepend,SdFile parent)
dir_t p; dir_t p;
uint8_t cnt=0; uint8_t cnt=0;
while (parent.readDir(p, diveFilename) > 0) while (parent.readDir(p, longFilename) > 0)
{ {
if( DIR_IS_SUBDIR(&p) && lsAction!=LS_Count && lsAction!=LS_GetFilename) // hence LS_SerialPrint if( DIR_IS_SUBDIR(&p) && lsAction!=LS_Count && lsAction!=LS_GetFilename) // hence LS_SerialPrint
{ {
@ -96,8 +91,8 @@ void CardReader::lsDive(const char *prepend,SdFile parent)
{ {
if (p.name[0] == DIR_NAME_FREE) break; if (p.name[0] == DIR_NAME_FREE) break;
if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue; if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue;
if (diveFilename[0] != '\0' && if (longFilename[0] != '\0' &&
(diveFilename[0] == '.' || diveFilename[0] == '_')) continue; (longFilename[0] == '.' || longFilename[0] == '_')) continue;
if ( p.name[0] == '.') if ( p.name[0] == '.')
{ {
if ( p.name[1] != '.') if ( p.name[1] != '.')
@ -556,21 +551,20 @@ void CardReader::closefile(bool store_location)
} }
void CardReader::getfilename(const uint8_t nr) void CardReader::getfilename(const uint16_t nr)
{ {
#if defined(SDCARD_SORT_ALPHA) && SORT_USES_MORE_RAM #if defined(SDCARD_SORT_ALPHA) && SORT_USES_RAM && SORT_USES_MORE_RAM
if (nr < sort_count) { if (nr < sort_count) {
strcpy(diveFilename, sortnames[nr]); strcpy(longFilename, sortnames[nr]);
filenameIsDir = isDir[nr];
return; return;
} }
#endif #endif
curDir=&workDir; curDir=&workDir;
lsAction=LS_GetFilename; lsAction=LS_GetFilename;
nrFiles=nr; nrFiles=nr;
curDir->rewind(); curDir->rewind();
lsDive("",*curDir); lsDive("",*curDir);
} }
uint16_t CardReader::getnrfilenames() uint16_t CardReader::getnrfilenames()
@ -631,12 +625,8 @@ void CardReader::updir()
/** /**
* Get the name of a file in the current directory by sort-index * Get the name of a file in the current directory by sort-index
*/ */
void CardReader::getfilename_sorted(const uint8_t nr) { void CardReader::getfilename_sorted(const uint16_t nr) {
#if SORT_USES_MORE_RAM
getfilename(nr < sort_count ? sort_order[nr] : nr); getfilename(nr < sort_count ? sort_order[nr] : nr);
#else
getfilename(nr < SORT_LIMIT ? sort_order[nr] : nr);
#endif
} }
/** /**
@ -656,68 +646,73 @@ void CardReader::presort()
if (fileCnt > SORT_LIMIT) fileCnt = SORT_LIMIT; if (fileCnt > SORT_LIMIT) fileCnt = SORT_LIMIT;
#if SORT_USES_RAM
#if SORT_USES_MORE_RAM #if SORT_USES_MORE_RAM
sortnames = (char**)malloc(fileCnt * sizeof(char*)); sortnames = (char**)calloc(fileCnt, sizeof(char*));
sort_count = fileCnt; #else
#elif SORT_USES_RAM
char *sortnames[fileCnt]; char *sortnames[fileCnt];
#if FOLDER_SORTING != 0
uint8_t isdir[fileCnt];
#endif #endif
#else #else
char sortname[LONG_FILENAME_LENGTH+1]; char name1[LONG_FILENAME_LENGTH+1];
#endif #endif
#if FOLDER_SORTING != 0
#if SORT_USES_RAM && SORT_USES_MORE_RAM
isDir = (uint8_t*)calloc(fileCnt, sizeof(uint8_t));
#else
uint8_t isDir[fileCnt];
#endif
#endif
sort_count = fileCnt;
sort_order = new uint8_t[fileCnt];
if (fileCnt > 1) { if (fileCnt > 1) {
// Init sort order [and get filenames] // Init sort order. If using RAM then read all filenames now.
for (int i=0; i<fileCnt; i++) { for (uint16_t i=0; i<fileCnt; i++) {
int byte=i/8, bit=1<<(i%8);
sort_order[i] = i; sort_order[i] = i;
#if SORT_USES_RAM #if SORT_USES_RAM
getfilename(i); getfilename(i);
char *name = diveFilename[0] ? diveFilename : filename; sortnames[i] = strdup(longFilename[0] ? longFilename : filename);
// SERIAL_ECHOPGM("--- "); // char out[30];
// SERIAL_ECHOLN(name); // sprintf_P(out, PSTR("---- %i %s %s"), i, filenameIsDir ? "D" : " ", sortnames[i]);
sortnames[i] = (char*)malloc(strlen(name) + 1); // SERIAL_ECHOLN(out);
strcpy(sortnames[i], name);
#if FOLDER_SORTING != 0 #if FOLDER_SORTING != 0
isdir[i] = filenameIsDir; isDir[i] = filenameIsDir;
#endif #endif
#endif #endif
} }
// Bubble Sort // Bubble Sort
for (uint8_t i=fileCnt; --i;) { for (uint16_t i=fileCnt; --i;) {
bool cmp, didSwap = false; bool cmp, didSwap = false;
for (uint8_t j=0; j<i; ++j) { for (uint16_t j=0; j<i; ++j) {
int s1 = j, s2 = j+1, o1 = sort_order[s1], o2 = sort_order[s2]; uint16_t s1 = j, s2 = j+1, o1 = sort_order[s1], o2 = sort_order[s2];
#if SORT_USES_RAM #if SORT_USES_RAM
#if FOLDER_SORTING != 0 #if FOLDER_SORTING != 0
cmp = (isdir[o1] == isdir[o2]) ? (strcasecmp(sortnames[o1], sortnames[o2]) > 0) : isdir[FOLDER_SORTING > 0 ? o1 : o2]; cmp = (isDir[o1] == isDir[o2]) ? (strcasecmp(sortnames[o1], sortnames[o2]) > 0) : isDir[FOLDER_SORTING > 0 ? o1 : o2];
#else #else
cmp = strcasecmp(sortnames[o1], sortnames[o2]) > 0); cmp = strcasecmp(sortnames[o1], sortnames[o2]) > 0;
#endif #endif
#else #else
getfilename(o1); getfilename(o1);
strcpy(name1, longFilename[0] ? longFilename : filename);
#if FOLDER_SORTING != 0 #if FOLDER_SORTING != 0
bool dir1 = filenameIsDir; bool dir1 = filenameIsDir;
#endif #endif
char *name = diveFilename[0] ? diveFilename : filename;
strcpy(sortname, name);
getfilename(o2); getfilename(o2);
name = diveFilename[0] ? diveFilename : filename; char *name2 = longFilename[0] ? longFilename : filename;
#if FOLDER_SORTING != 0 #if FOLDER_SORTING != 0
cmp = (dir1 == filenameIsDir) ? (strcasecmp(sortname, name) > 0) : (FOLDER_SORTING > 0 ? dir1 : !dir1); cmp = (dir1 == filenameIsDir) ? (strcasecmp(name1, name2) > 0) : (FOLDER_SORTING > 0 ? dir1 : !dir1);
#else #else
cmp = strcasecmp(sortname, name) > 0); cmp = strcasecmp(name1, name2) > 0;
#endif #endif
#endif #endif
if (cmp) { if (cmp) {
// SERIAL_ECHOPGM("Swap "); // char out[LONG_FILENAME_LENGTH*2+20];
// SERIAL_ECHOLN(sortnames[o1]); // sprintf_P(out, PSTR("Swap %i %s for %i %s"), o1, sortnames[o1], o2, sortnames[o2]);
// SERIAL_ECHOPGM(" for "); // SERIAL_ECHOLN(out);
// SERIAL_ECHOLN(sortnames[o2]);
sort_order[s1] = o2; sort_order[s1] = o2;
sort_order[s2] = o1; sort_order[s2] = o1;
didSwap = true; didSwap = true;
@ -727,30 +722,32 @@ void CardReader::presort()
} }
#if SORT_USES_RAM && !SORT_USES_MORE_RAM #if SORT_USES_RAM && !SORT_USES_MORE_RAM
for (int i=0; i < fileCnt; ++i) free(sortnames[i]); for (uint16_t i=0; i<fileCnt; ++i) free(sortnames[i]);
#endif #endif
} }
else { else {
sort_order[0] = 0; sort_order[0] = 0;
#if SORT_USES_RAM && SORT_USES_MORE_RAM
sortnames = (char**)malloc(sizeof(char*));
isDir = (uint8_t*)malloc(sizeof(uint8_t));
getfilename(0);
sortnames[0] = strdup(longFilename[0] ? longFilename : filename);
isDir[0] = filenameIsDir;
#endif
} }
} }
} }
void CardReader::flush_presort() { void CardReader::flush_presort() {
#if SORT_USES_MORE_RAM
if (sort_count > 0) { if (sort_count > 0) {
for (int i=0; i < sort_count; ++i) { #if SORT_USES_RAM && SORT_USES_MORE_RAM
free(sortnames[i]); for (uint8_t i=0; i<sort_count; ++i) free(sortnames[i]);
sort_order[i] = i;
}
free(sortnames); free(sortnames);
sortnames = NULL; #endif
delete sort_order;
sort_count = 0; sort_count = 0;
} }
#else
for (int i=SORT_LIMIT; --i;) sort_order[i] = i;
#endif
} }
#endif // SDCARD_SORT_ALPHA #endif // SDCARD_SORT_ALPHA

View File

@ -6,7 +6,7 @@
#define MAX_DIR_DEPTH 10 // Maximum folder depth #define MAX_DIR_DEPTH 10 // Maximum folder depth
#define SORT_USES_RAM false // Buffer while sorting, else re-read from SD #define SORT_USES_RAM false // Buffer while sorting, else re-read from SD
#define SORT_USES_MORE_RAM false // Always keep the directory in RAM #define SORT_USES_MORE_RAM false // Always keep the directory in RAM
#define SORT_LIMIT 256 // Maximum number of sorted items #define SORT_LIMIT 64 // Maximum number of sorted items
#define FOLDER_SORTING -1 // -1=above 0=none 1=below #define FOLDER_SORTING -1 // -1=above 0=none 1=below
#include "SdFile.h" #include "SdFile.h"
@ -32,7 +32,7 @@ public:
void getStatus(); void getStatus();
void printingHasFinished(); void printingHasFinished();
void getfilename(const uint8_t nr); void getfilename(const uint16_t nr);
uint16_t getnrfilenames(); uint16_t getnrfilenames();
void getAbsFilename(char *t); void getAbsFilename(char *t);
@ -46,7 +46,7 @@ public:
#ifdef SDCARD_SORT_ALPHA #ifdef SDCARD_SORT_ALPHA
void presort(); void presort();
void flush_presort(); void flush_presort();
void getfilename_sorted(const uint8_t nr); void getfilename_sorted(const uint16_t nr);
#endif #endif
@ -63,18 +63,18 @@ public:
bool sdprinting; bool sdprinting;
bool cardOK; bool cardOK;
char filename[FILENAME_LENGTH]; char filename[FILENAME_LENGTH];
char diveFilename[LONG_FILENAME_LENGTH]; char longFilename[LONG_FILENAME_LENGTH];
bool filenameIsDir; bool filenameIsDir;
int lastnr; //last number of the autostart; int lastnr; //last number of the autostart;
private: private:
SdFile root,*curDir,workDir,workDirParents[MAX_DIR_DEPTH]; SdFile root,*curDir,workDir,workDirParents[MAX_DIR_DEPTH];
uint16_t workDirDepth; uint16_t workDirDepth;
#ifdef SDCARD_SORT_ALPHA #ifdef SDCARD_SORT_ALPHA
#if SORT_USES_MORE_RAM
uint16_t sort_count; uint16_t sort_count;
uint8_t *sort_order;
#if SORT_USES_MORE_RAM
char **sortnames; char **sortnames;
#else uint8_t *isDir;
uint8_t sort_order[SORT_LIMIT];
#endif #endif
#endif #endif
Sd2Card card; Sd2Card card;
@ -93,7 +93,7 @@ private:
bool autostart_stilltocheck; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware. bool autostart_stilltocheck; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware.
LsAction lsAction; //stored for recursion. LsAction lsAction; //stored for recursion.
int16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory. uint16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory.
char* diveDirName; char* diveDirName;
void lsDive(const char *prepend,SdFile parent); void lsDive(const char *prepend,SdFile parent);
}; };

View File

@ -970,10 +970,10 @@ void lcd_sdcard_menu()
#endif #endif
if (card.filenameIsDir) { if (card.filenameIsDir) {
MENU_ITEM(sddirectory, MSG_CARD_MENU, card.filename, card.diveFilename); MENU_ITEM(sddirectory, MSG_CARD_MENU, card.filename, card.longFilename);
} }
else { else {
MENU_ITEM(sdfile, MSG_CARD_MENU, card.filename, card.diveFilename); MENU_ITEM(sdfile, MSG_CARD_MENU, card.filename, card.longFilename);
} }
}else{ }else{
MENU_ITEM_DUMMY(); MENU_ITEM_DUMMY();