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:
parent
785143a013
commit
ae081d0fe0
3 changed files with 78 additions and 81 deletions
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1017,10 +1017,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();
|
||||||
|
|
Reference in a new issue