Skip to content

Commit 78d178b

Browse files
vovodroidthinkyhead
authored andcommitted
🔧 Reversible file alpha sorting (MarlinFirmware#26130)
Co-authored-by: Scott Lahteine <thinkyhead@users.noreply.github.com>
1 parent a8eafca commit 78d178b

File tree

9 files changed

+66
-45
lines changed

9 files changed

+66
-45
lines changed

Marlin/Configuration_adv.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -1752,10 +1752,11 @@
17521752

17531753
// SD Card Sorting options
17541754
#if ENABLED(SDCARD_SORT_ALPHA)
1755+
#define SDSORT_REVERSE false // Default to sorting file names in reverse order.
17551756
#define SDSORT_LIMIT 40 // Maximum number of sorted items (10-256). Costs 27 bytes each.
1756-
#define FOLDER_SORTING -1 // -1=above 0=none 1=below
1757-
#define SDSORT_GCODE false // Allow turning sorting on/off with LCD and M34 G-code.
1758-
#define SDSORT_USES_RAM true // Pre-allocate a static array for faster pre-sorting.
1757+
#define SDSORT_FOLDERS -1 // -1=above 0=none 1=below
1758+
#define SDSORT_GCODE false // Enable G-code M34 to set sorting behaviors: M34 S<-1|0|1> F<-1|0|1>
1759+
#define SDSORT_USES_RAM false // Pre-allocate a static array for faster pre-sorting.
17591760
#define SDSORT_USES_STACK false // Prefer the stack for pre-sorting to give back some SRAM. (Negated by next 2 options.)
17601761
#define SDSORT_CACHE_NAMES true // Keep sorted items in RAM longer for speedy performance. Most expensive option.
17611762
#define SDSORT_DYNAMIC_RAM false // Use dynamic allocation (within SD menus). Least expensive option. Set SDSORT_LIMIT before use!

Marlin/src/gcode/sd/M34.cpp

+11-1
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,19 @@
2929

3030
/**
3131
* M34: Set SD Card Sorting Options
32+
*
33+
* S - Default sorting (i.e., SDSORT_REVERSE)
34+
* S-1 - Reverse alpha sorting
35+
* S0 - FID Order (not always newest)
36+
* S1 - Forward alpha sorting
37+
* S2 - Alias for S-1 [deprecated]
38+
*
39+
* F-1 - Folders above files
40+
* F0 - Sort According to 'S'
41+
* F1 - Folders after files
3242
*/
3343
void GcodeSuite::M34() {
34-
if (parser.seen('S')) card.setSortOn(parser.value_bool());
44+
if (parser.seen('S')) card.setSortOn(SortFlag(parser.ushortval('S', TERN(SDSORT_REVERSE, AS_REV, AS_FWD))));
3545
if (parser.seenval('F')) {
3646
const int v = parser.value_long();
3747
card.setSortFolders(v < 0 ? -1 : v > 0 ? 1 : 0);

Marlin/src/inc/Changes.h

+2
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,8 @@
661661
#error "Z4_USE_ENDSTOP is obsolete. Instead set Z4_STOP_PIN directly. (e.g., 'Z4_USE_ENDSTOP _ZMAX_' becomes 'Z4_STOP_PIN Z_MAX_PIN')"
662662
#elif defined(INTEGRATED_BABYSTEPPING)
663663
#error "INTEGRATED_BABYSTEPPING is no longer needed and should be removed."
664+
#elif defined(FOLDER_SORTING)
665+
#error "FOLDER_SORTING is now SDSORT_FOLDERS."
664666
#endif
665667

666668
// L64xx stepper drivers have been removed

Marlin/src/inc/Conditionals_post.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -3337,8 +3337,8 @@
33373337
#define SDSORT_CACHE_NAMES true
33383338
#define SDSORT_CACHE_LPC1768_WARNING 1
33393339
#endif
3340-
#ifndef FOLDER_SORTING
3341-
#define FOLDER_SORTING -1
3340+
#ifndef SDSORT_FOLDERS
3341+
#define SDSORT_FOLDERS -1
33423342
#endif
33433343
#ifndef SDSORT_GCODE
33443344
#define SDSORT_GCODE false

Marlin/src/lcd/e3v2/proui/dwin.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -850,7 +850,7 @@ bool DWIN_lcd_sd_status = false;
850850
#if ENABLED(MEDIASORT_MENU_ITEM)
851851
void setMediaSort() {
852852
toggleCheckboxLine(hmiData.mediaSort);
853-
card.setSortOn(hmiData.mediaSort);
853+
card.setSortOn(hmiData.mediaSort ? TERN(SDSORT_REVERSE, AS_REV, AS_FWD) : AS_OFF);
854854
}
855855
#endif
856856

@@ -1754,7 +1754,7 @@ void dwinSetDataDefaults() {
17541754
#endif
17551755
#if ENABLED(MEDIASORT_MENU_ITEM)
17561756
hmiData.mediaSort = true;
1757-
card.setSortOn(true);
1757+
card.setSortOn(TERN(SDSORT_REVERSE, AS_REV, AS_FWD));
17581758
#endif
17591759
hmiData.mediaAutoMount = ENABLED(HAS_SD_EXTENDER);
17601760
#if ALL(INDIVIDUAL_AXIS_HOMING_SUBMENU, MESH_BED_LEVELING)

Marlin/src/sd/SdBaseFile.cpp

+8-6
Original file line numberDiff line numberDiff line change
@@ -1422,11 +1422,13 @@ int16_t SdBaseFile::read(void * const buf, uint16_t nbyte) {
14221422
*
14231423
* \param[out] dir The dir_t struct that will receive the data.
14241424
*
1425-
* \return For success readDir() returns the number of bytes read.
1426-
* A value of zero will be returned if end of file is reached.
1427-
* If an error occurs, readDir() returns -1. Possible errors include
1428-
* readDir() called before a directory has been opened, this is not
1429-
* a directory file or an I/O error occurred.
1425+
* \return For success return a non-zero value (number of bytes read).
1426+
* A value of zero will be returned if end of dir is reached.
1427+
* If an error occurs, readDir() returns -1. Possible errors:
1428+
* - readDir() called on unopened dir
1429+
* - not a directory file
1430+
* - bad dir entry
1431+
* - I/O error
14301432
*/
14311433
int8_t SdBaseFile::readDir(dir_t * const dir, char * const longFilename) {
14321434
int16_t n;
@@ -1488,7 +1490,7 @@ int8_t SdBaseFile::readDir(dir_t * const dir, char * const longFilename) {
14881490
longFilename[idx] = utf16_ch & 0xFF;
14891491
longFilename[idx + 1] = (utf16_ch >> 8) & 0xFF;
14901492
#else
1491-
// Replace all multibyte characters to '_'
1493+
// Replace multibyte character with '_'
14921494
longFilename[n + i] = (utf16_ch > 0xFF) ? '_' : (utf16_ch & 0xFF);
14931495
#endif
14941496
}

Marlin/src/sd/cardreader.cpp

+24-22
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ int16_t CardReader::nrItems = -1;
9191

9292
int16_t CardReader::sort_count;
9393
#if ENABLED(SDSORT_GCODE)
94-
bool CardReader::sort_alpha;
95-
int CardReader::sort_folders;
94+
SortFlag CardReader::sort_alpha;
95+
int8_t CardReader::sort_folders;
9696
//bool CardReader::sort_reverse;
9797
#endif
9898

@@ -160,8 +160,8 @@ CardReader::CardReader() {
160160
#if ENABLED(SDCARD_SORT_ALPHA)
161161
sort_count = 0;
162162
#if ENABLED(SDSORT_GCODE)
163-
sort_alpha = true;
164-
sort_folders = FOLDER_SORTING;
163+
sort_alpha = TERN(SDSORT_REVERSE, AS_REV, AS_FWD);
164+
sort_folders = SDSORT_FOLDERS;
165165
//sort_reverse = false;
166166
#endif
167167
#endif
@@ -993,7 +993,7 @@ void CardReader::selectFileByIndex(const int16_t nr) {
993993
if (nr < sort_count) {
994994
strcpy(filename, sortshort[nr]);
995995
strcpy(longFilename, sortnames[nr]);
996-
flag.filenameIsDir = IS_DIR(nr);
996+
TERN_(HAS_FOLDER_SORTING, flag.filenameIsDir = IS_DIR(nr));
997997
setBinFlag(strcmp_P(strrchr(filename, '.'), PSTR(".BIN")) == 0);
998998
return;
999999
}
@@ -1011,7 +1011,7 @@ void CardReader::selectFileByName(const char * const match) {
10111011
if (strcasecmp(match, sortshort[nr]) == 0) {
10121012
strcpy(filename, sortshort[nr]);
10131013
strcpy(longFilename, sortnames[nr]);
1014-
flag.filenameIsDir = IS_DIR(nr);
1014+
TERN_(HAS_FOLDER_SORTING, flag.filenameIsDir = IS_DIR(nr));
10151015
setBinFlag(strcmp_P(strrchr(filename, '.'), PSTR(".BIN")) == 0);
10161016
return;
10171017
}
@@ -1163,7 +1163,7 @@ void CardReader::cdroot() {
11631163
* Get the name of a file in the working directory by sort-index
11641164
*/
11651165
void CardReader::selectFileByIndexSorted(const int16_t nr) {
1166-
selectFileByIndex(TERN1(SDSORT_GCODE, sort_alpha) && (nr < sort_count) ? sort_order[nr] : nr);
1166+
selectFileByIndex(SortFlag(TERN1(SDSORT_GCODE, sort_alpha != AS_OFF)) && (nr < sort_count) ? sort_order[nr] : nr);
11671167
}
11681168

11691169
#if ENABLED(SDSORT_USES_RAM)
@@ -1210,7 +1210,7 @@ void CardReader::cdroot() {
12101210
int16_t fileCnt = get_num_items();
12111211

12121212
// Sorting may be turned off
1213-
if (TERN0(SDSORT_GCODE, !sort_alpha)) return;
1213+
if (TERN0(SDSORT_GCODE, sort_alpha == AS_OFF)) return;
12141214

12151215
// If there are files, sort up to the limit
12161216
if (fileCnt > 0) {
@@ -1239,9 +1239,9 @@ void CardReader::cdroot() {
12391239
// Folder sorting needs 1 bit per entry for flags.
12401240
#if HAS_FOLDER_SORTING
12411241
#if ENABLED(SDSORT_DYNAMIC_RAM)
1242-
isDir = new uint8_t[(fileCnt + 7) >> 3];
1242+
isDir = new uint8_t[(fileCnt + 7) >> 3]; // Allocate space with 'new'
12431243
#elif ENABLED(SDSORT_USES_STACK)
1244-
uint8_t isDir[(fileCnt + 7) >> 3];
1244+
uint8_t isDir[(fileCnt + 7) >> 3]; // Use stack in this scope
12451245
#endif
12461246
#endif
12471247

@@ -1291,18 +1291,18 @@ void CardReader::cdroot() {
12911291
const int16_t o2 = sort_order[j + 1];
12921292

12931293
// Compare names from the array or just the two buffered names
1294-
#if ENABLED(SDSORT_USES_RAM)
1295-
#define _SORT_CMP_NODIR() (strcasecmp(sortnames[o1], sortnames[o2]) > 0)
1296-
#else
1297-
#define _SORT_CMP_NODIR() (strcasecmp(name1, name2) > 0)
1298-
#endif
1294+
auto _sort_cmp_file = [](char * const n1, char * const n2) -> bool {
1295+
const bool sort = strcasecmp(n1, n2) > 0;
1296+
return (TERN(SDSORT_GCODE, card.sort_alpha == AS_REV, ENABLED(SDSORT_REVERSE))) ? !sort : sort;
1297+
};
1298+
#define _SORT_CMP_FILE() _sort_cmp_file(TERN(SDSORT_USES_RAM, sortnames[o1], name1), TERN(SDSORT_USES_RAM, sortnames[o2], name2))
12991299

13001300
#if HAS_FOLDER_SORTING
13011301
#if ENABLED(SDSORT_USES_RAM)
13021302
// Folder sorting needs an index and bit to test for folder-ness.
1303-
#define _SORT_CMP_DIR(fs) (IS_DIR(o1) == IS_DIR(o2) ? _SORT_CMP_NODIR() : IS_DIR(fs > 0 ? o1 : o2))
1303+
#define _SORT_CMP_DIR(fs) (IS_DIR(o1) == IS_DIR(o2) ? _SORT_CMP_FILE() : IS_DIR(fs > 0 ? o1 : o2))
13041304
#else
1305-
#define _SORT_CMP_DIR(fs) ((dir1 == flag.filenameIsDir) ? _SORT_CMP_NODIR() : (fs > 0 ? dir1 : !dir1))
1305+
#define _SORT_CMP_DIR(fs) ((dir1 == flag.filenameIsDir) ? _SORT_CMP_FILE() : (fs > 0 ? dir1 : !dir1))
13061306
#endif
13071307
#endif
13081308

@@ -1318,12 +1318,12 @@ void CardReader::cdroot() {
13181318
if (
13191319
#if HAS_FOLDER_SORTING
13201320
#if ENABLED(SDSORT_GCODE)
1321-
sort_folders ? _SORT_CMP_DIR(sort_folders) : _SORT_CMP_NODIR()
1321+
sort_folders ? _SORT_CMP_DIR(sort_folders) : _SORT_CMP_FILE()
13221322
#else
1323-
_SORT_CMP_DIR(FOLDER_SORTING)
1323+
_SORT_CMP_DIR(SDSORT_FOLDERS)
13241324
#endif
13251325
#else
1326-
_SORT_CMP_NODIR()
1326+
_SORT_CMP_FILE()
13271327
#endif
13281328
) {
13291329
// Reorder the index, indicate that sorting happened
@@ -1357,12 +1357,14 @@ void CardReader::cdroot() {
13571357
#if ENABLED(SDSORT_DYNAMIC_RAM)
13581358
sortnames = new char*[1];
13591359
sortshort = new char*[1];
1360-
isDir = new uint8_t[1];
13611360
#endif
13621361
selectFileByIndex(0);
13631362
SET_SORTNAME(0);
13641363
SET_SORTSHORT(0);
1365-
isDir[0] = flag.filenameIsDir;
1364+
#if ALL(HAS_FOLDER_SORTING, SDSORT_DYNAMIC_RAM)
1365+
isDir = new uint8_t[1];
1366+
isDir[0] = flag.filenameIsDir;
1367+
#endif
13661368
#endif
13671369
}
13681370

Marlin/src/sd/cardreader.h

+10-6
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ extern const char M23_STR[], M24_STR[];
3131
#if ENABLED(SDSORT_DYNAMIC_RAM)
3232
#define SD_RESORT 1
3333
#endif
34-
#if FOLDER_SORTING || ENABLED(SDSORT_GCODE)
34+
#ifndef SDSORT_FOLDERS
35+
#define SDSORT_FOLDERS 0
36+
#endif
37+
#if SDSORT_FOLDERS || ENABLED(SDSORT_GCODE)
3538
#define HAS_FOLDER_SORTING 1
3639
#endif
3740
#endif
@@ -84,6 +87,7 @@ typedef struct {
8487
} card_flags_t;
8588

8689
enum ListingFlags : uint8_t { LS_LONG_FILENAME, LS_ONLY_BIN, LS_TIMESTAMP };
90+
enum SortFlag : int8_t { AS_REV = -1, AS_OFF, AS_FWD, AS_ALSO_REV };
8791

8892
#if ENABLED(AUTO_REPORT_SD_STATUS)
8993
#include "../libs/autoreport.h"
@@ -199,8 +203,8 @@ class CardReader {
199203
static void presort();
200204
static void selectFileByIndexSorted(const int16_t nr);
201205
#if ENABLED(SDSORT_GCODE)
202-
FORCE_INLINE static void setSortOn(bool b) { sort_alpha = b; presort(); }
203-
FORCE_INLINE static void setSortFolders(int i) { sort_folders = i; presort(); }
206+
FORCE_INLINE static void setSortOn(const SortFlag f) { sort_alpha = (f == AS_ALSO_REV) ? AS_REV : f; presort(); }
207+
FORCE_INLINE static void setSortFolders(const int8_t i) { sort_folders = i; presort(); }
204208
//FORCE_INLINE static void setSortReverse(bool b) { sort_reverse = b; }
205209
#endif
206210
#else
@@ -272,12 +276,12 @@ class CardReader {
272276
#if ENABLED(SDCARD_SORT_ALPHA)
273277
static int16_t sort_count; // Count of sorted items in the current directory
274278
#if ENABLED(SDSORT_GCODE)
275-
static bool sort_alpha; // Flag to enable / disable the feature
276-
static int sort_folders; // Folder sorting before/none/after
279+
static SortFlag sort_alpha; // Sorting: REV, OFF, FWD
280+
static int8_t sort_folders; // Folder sorting before/none/after
277281
//static bool sort_reverse; // Flag to enable / disable reverse sorting
278282
#endif
279283

280-
// By default the sort index is static
284+
// By default the sort index is statically allocated
281285
#if ENABLED(SDSORT_DYNAMIC_RAM)
282286
static uint8_t *sort_order;
283287
#else

buildroot/tests/STM32F103VE_longer_maple

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@ set -e
88

99
use_example_configs Alfawise/U20
1010
opt_enable BAUD_RATE_GCODE
11-
exec_test $1 $2 "maple CLASSIC_UI U20 config" "$3"
11+
exec_test $1 $2 "Maple - Alfawise U20 - CLASSIC_UI" "$3"
1212

1313
use_example_configs Alfawise/U20
1414
opt_enable BAUD_RATE_GCODE TFT_COLOR_UI
1515
opt_disable TFT_CLASSIC_UI CUSTOM_STATUS_SCREEN_IMAGE
16-
exec_test $1 $2 "maple COLOR_UI U20 config" "$3"
16+
exec_test $1 $2 "Maple - Alfawise U20 - COLOR_UI" "$3"
1717

1818
use_example_configs Alfawise/U20-bltouch
1919
opt_enable BAUD_RATE_GCODE
20-
exec_test $1 $2 "maple BLTouch U20 config"
20+
exec_test $1 $2 "Maple - Alfawise U20 - BLTouch"
2121

2222
# cleanup
2323
restore_configs

0 commit comments

Comments
 (0)