Merge pull request #2405 from leptun/MK3_NEW_SD_COMPILATION
⚡️New SD menu
This commit is contained in:
commit
c1849f5cc2
12 changed files with 425 additions and 572 deletions
|
@ -231,33 +231,23 @@
|
||||||
* SD sorting uses static allocation (as set by SDSORT_LIMIT), allowing the
|
* SD sorting uses static allocation (as set by SDSORT_LIMIT), allowing the
|
||||||
* compiler to calculate the worst-case usage and throw an error if the SRAM
|
* compiler to calculate the worst-case usage and throw an error if the SRAM
|
||||||
* limit is exceeded.
|
* limit is exceeded.
|
||||||
*
|
|
||||||
* - SDSORT_USES_RAM provides faster sorting via a static directory buffer.
|
|
||||||
* - SDSORT_USES_STACK does the same, but uses a local stack-based buffer.
|
|
||||||
* - SDSORT_CACHE_NAMES will retain the sorted file listing in RAM. (Expensive!)
|
|
||||||
* - SDSORT_DYNAMIC_RAM only uses RAM when the SD menu is visible. (Use with caution!)
|
|
||||||
*/
|
*/
|
||||||
#define SDCARD_SORT_ALPHA //Alphabetical sorting of SD files menu
|
#define SDCARD_SORT_ALPHA //Alphabetical sorting of SD files menu
|
||||||
|
|
||||||
// SD Card Sorting options
|
// SD Card Sorting options
|
||||||
// In current firmware Prusa Firmware version,
|
|
||||||
// SDSORT_CACHE_NAMES and SDSORT_DYNAMIC_RAM is not supported and must be set to 0.
|
|
||||||
#ifdef SDCARD_SORT_ALPHA
|
#ifdef SDCARD_SORT_ALPHA
|
||||||
#define SD_SORT_TIME 0
|
#define SD_SORT_TIME 0
|
||||||
#define SD_SORT_ALPHA 1
|
#define SD_SORT_ALPHA 1
|
||||||
#define SD_SORT_NONE 2
|
#define SD_SORT_NONE 2
|
||||||
|
// #define SHELLSORT
|
||||||
|
// #define SORTING_DUMP
|
||||||
|
|
||||||
#define SDSORT_LIMIT 100 // Maximum number of sorted items (10-256).
|
#define SDSORT_LIMIT 100 // Maximum number of sorted items (10-256).
|
||||||
#define FOLDER_SORTING -1 // -1=above 0=none 1=below
|
#define FOLDER_SORTING -1 // -1=above 0=none 1=below
|
||||||
#define SDSORT_GCODE 0 // Allow turning sorting on/off with LCD and M34 g-code.
|
|
||||||
#define SDSORT_USES_RAM 0 // Pre-allocate a static array for faster pre-sorting.
|
|
||||||
#define SDSORT_USES_STACK 0 // Prefer the stack for pre-sorting to give back some SRAM. (Negated by next 2 options.)
|
|
||||||
#define SDSORT_CACHE_NAMES 0 // Keep sorted items in RAM longer for speedy performance. Most expensive option.
|
|
||||||
#define SDSORT_DYNAMIC_RAM 0 // Use dynamic allocation (within SD menus). Least expensive option. Set SDSORT_LIMIT before use!
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(SDCARD_SORT_ALPHA)
|
#if defined(SDCARD_SORT_ALPHA)
|
||||||
#define HAS_FOLDER_SORTING (FOLDER_SORTING || SDSORT_GCODE)
|
#define HAS_FOLDER_SORTING (FOLDER_SORTING)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Enable the option to stop SD printing when hitting and endstops, needs to be enabled from the LCD menu when this option is enabled.
|
// Enable the option to stop SD printing when hitting and endstops, needs to be enabled from the LCD menu when this option is enabled.
|
||||||
|
|
|
@ -766,31 +766,16 @@ static void factory_reset(char level)
|
||||||
#endif //FILAMENT_SENSOR
|
#endif //FILAMENT_SENSOR
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:{ // Level 3: erase everything, whole EEPROM will be set to 0xFF
|
case 3:
|
||||||
lcd_puts_P(PSTR("Factory RESET"));
|
menu_progressbar_init(EEPROM_TOP, PSTR("ERASING all data"));
|
||||||
lcd_puts_at_P(1, 2, PSTR("ERASING all data"));
|
|
||||||
uint16_t er_progress = 0;
|
|
||||||
lcd_set_cursor(3, 3);
|
|
||||||
lcd_space(6);
|
|
||||||
lcd_set_cursor(3, 3);
|
|
||||||
lcd_print(er_progress);
|
|
||||||
|
|
||||||
// Erase EEPROM
|
// Erase EEPROM
|
||||||
for (uint16_t i = 0; i < 4096; i++) {
|
for (uint16_t i = 0; i < EEPROM_TOP; i++) {
|
||||||
eeprom_update_byte((uint8_t*)i, 0xFF);
|
eeprom_update_byte((uint8_t*)i, 0xFF);
|
||||||
|
menu_progressbar_update(i);
|
||||||
if (i % 41 == 0) {
|
|
||||||
er_progress++;
|
|
||||||
lcd_set_cursor(3, 3);
|
|
||||||
lcd_space(6);
|
|
||||||
lcd_set_cursor(3, 3);
|
|
||||||
lcd_print(er_progress);
|
|
||||||
lcd_puts_P(PSTR("%"));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
menu_progressbar_finish();
|
||||||
softReset();
|
softReset();
|
||||||
}break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
#ifdef SNMM
|
#ifdef SNMM
|
||||||
|
@ -11272,7 +11257,7 @@ void restore_print_from_eeprom(bool mbl_was_active) {
|
||||||
}
|
}
|
||||||
dir_name[8] = '\0';
|
dir_name[8] = '\0';
|
||||||
MYSERIAL.println(dir_name);
|
MYSERIAL.println(dir_name);
|
||||||
// strcpy(dir_names[i], dir_name);
|
// strcpy(card.dir_names[i], dir_name);
|
||||||
card.chdir(dir_name, false);
|
card.chdir(dir_name, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,11 +15,6 @@ CardReader::CardReader()
|
||||||
|
|
||||||
#ifdef SDCARD_SORT_ALPHA
|
#ifdef SDCARD_SORT_ALPHA
|
||||||
sort_count = 0;
|
sort_count = 0;
|
||||||
#if SDSORT_GCODE
|
|
||||||
sort_alpha = true;
|
|
||||||
sort_folders = FOLDER_SORTING;
|
|
||||||
//sort_reverse = false;
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
filesize = 0;
|
filesize = 0;
|
||||||
|
@ -82,7 +77,7 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
|
||||||
dir_t p;
|
dir_t p;
|
||||||
uint8_t cnt = 0;
|
uint8_t cnt = 0;
|
||||||
// Read the next entry from a directory
|
// Read the next entry from a directory
|
||||||
while (parent.readDir(p, longFilename) > 0) {
|
for (position = parent.curPosition(); parent.readDir(p, longFilename) > 0; position = parent.curPosition()) {
|
||||||
if (recursionCnt > MAX_DIR_DEPTH)
|
if (recursionCnt > MAX_DIR_DEPTH)
|
||||||
return;
|
return;
|
||||||
else if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) { // If the entry is a directory and the action is LS_SerialPrint
|
else if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) { // If the entry is a directory and the action is LS_SerialPrint
|
||||||
|
@ -149,10 +144,10 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LS_GetFilename:
|
case LS_GetFilename:
|
||||||
//SERIAL_ECHOPGM("File: ");
|
//SERIAL_ECHOPGM("File: ");
|
||||||
createFilename(filename, p);
|
createFilename(filename, p);
|
||||||
cluster = parent.curCluster();
|
// cluster = parent.curCluster();
|
||||||
position = parent.curPosition();
|
// position = parent.curPosition();
|
||||||
/*MYSERIAL.println(filename);
|
/*MYSERIAL.println(filename);
|
||||||
SERIAL_ECHOPGM("Write date: ");
|
SERIAL_ECHOPGM("Write date: ");
|
||||||
writeDate = p.lastWriteDate;
|
writeDate = p.lastWriteDate;
|
||||||
|
@ -397,7 +392,7 @@ static const char ofNowFreshFile[] PROGMEM = "Now fresh file: ";
|
||||||
static const char ofFileOpened[] PROGMEM = "File opened: ";
|
static const char ofFileOpened[] PROGMEM = "File opened: ";
|
||||||
static const char ofSize[] PROGMEM = " Size: ";
|
static const char ofSize[] PROGMEM = " Size: ";
|
||||||
static const char ofFileSelected[] PROGMEM = "File selected";
|
static const char ofFileSelected[] PROGMEM = "File selected";
|
||||||
static const char ofSDPrinting[] PROGMEM = "SD-PRINTING ";
|
static const char ofSDPrinting[] PROGMEM = "SD-PRINTING";
|
||||||
static const char ofWritingToFile[] PROGMEM = "Writing to file: ";
|
static const char ofWritingToFile[] PROGMEM = "Writing to file: ";
|
||||||
|
|
||||||
void CardReader::openFileReadFilteredGcode(const char* name, bool replace_current/* = false*/){
|
void CardReader::openFileReadFilteredGcode(const char* name, bool replace_current/* = false*/){
|
||||||
|
@ -446,17 +441,17 @@ void CardReader::openFileReadFilteredGcode(const char* name, bool replace_curren
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (file.openFilteredGcode(curDir, fname)) {
|
if (file.openFilteredGcode(curDir, fname)) {
|
||||||
|
getfilename(0, fname);
|
||||||
filesize = file.fileSize();
|
filesize = file.fileSize();
|
||||||
SERIAL_PROTOCOLRPGM(ofFileOpened);////MSG_SD_FILE_OPENED
|
SERIAL_PROTOCOLRPGM(ofFileOpened);////MSG_SD_FILE_OPENED
|
||||||
SERIAL_PROTOCOL(fname);
|
printAbsFilenameFast();
|
||||||
SERIAL_PROTOCOLRPGM(ofSize);////MSG_SD_SIZE
|
SERIAL_PROTOCOLRPGM(ofSize);////MSG_SD_SIZE
|
||||||
SERIAL_PROTOCOLLN(filesize);
|
SERIAL_PROTOCOLLN(filesize);
|
||||||
sdpos = 0;
|
sdpos = 0;
|
||||||
|
|
||||||
SERIAL_PROTOCOLLNRPGM(ofFileSelected);////MSG_SD_FILE_SELECTED
|
SERIAL_PROTOCOLLNRPGM(ofFileSelected);////MSG_SD_FILE_SELECTED
|
||||||
getfilename(0, fname);
|
lcd_setstatuspgm(ofFileSelected);
|
||||||
lcd_setstatus(longFilename[0] ? longFilename : fname);
|
scrollstuff = 0;
|
||||||
lcd_setstatuspgm(ofSDPrinting);
|
|
||||||
} else {
|
} else {
|
||||||
SERIAL_PROTOCOLRPGM(MSG_SD_OPEN_FILE_FAIL);
|
SERIAL_PROTOCOLRPGM(MSG_SD_OPEN_FILE_FAIL);
|
||||||
SERIAL_PROTOCOL(fname);
|
SERIAL_PROTOCOL(fname);
|
||||||
|
@ -517,9 +512,14 @@ void CardReader::openFileWrite(const char* name)
|
||||||
SERIAL_PROTOCOLLN('.');
|
SERIAL_PROTOCOLLN('.');
|
||||||
} else {
|
} else {
|
||||||
saving = true;
|
saving = true;
|
||||||
|
getfilename(0, fname);
|
||||||
SERIAL_PROTOCOLRPGM(ofWritingToFile);////MSG_SD_WRITE_TO_FILE
|
SERIAL_PROTOCOLRPGM(ofWritingToFile);////MSG_SD_WRITE_TO_FILE
|
||||||
SERIAL_PROTOCOLLN(fname);
|
printAbsFilenameFast();
|
||||||
lcd_setstatus(fname);
|
SERIAL_PROTOCOLLN();
|
||||||
|
|
||||||
|
SERIAL_PROTOCOLLNRPGM(ofFileSelected);////MSG_SD_FILE_SELECTED
|
||||||
|
lcd_setstatuspgm(ofFileSelected);
|
||||||
|
scrollstuff = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -711,6 +711,15 @@ void CardReader::getfilename_simple(uint32_t position, const char * const match/
|
||||||
lsDive("", *curDir, match);
|
lsDive("", *curDir, match);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CardReader::getfilename_next(uint32_t position, const char * const match/*=NULL*/)
|
||||||
|
{
|
||||||
|
curDir = &workDir;
|
||||||
|
lsAction = LS_GetFilename;
|
||||||
|
nrFiles = 1;
|
||||||
|
curDir->seekSet(position);
|
||||||
|
lsDive("", *curDir, match);
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t CardReader::getnrfilenames()
|
uint16_t CardReader::getnrfilenames()
|
||||||
{
|
{
|
||||||
curDir=&workDir;
|
curDir=&workDir;
|
||||||
|
@ -780,13 +789,11 @@ 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 uint16_t nr) {
|
void CardReader::getfilename_sorted(const uint16_t nr, uint8_t sdSort) {
|
||||||
getfilename(
|
if (nr < sort_count)
|
||||||
#if SDSORT_GCODE
|
getfilename_simple(sort_positions[(sdSort == SD_SORT_ALPHA) ? (sort_count - nr - 1) : nr]);
|
||||||
sort_alpha &&
|
else
|
||||||
#endif
|
getfilename(nr);
|
||||||
(nr < sort_count) ? sort_order[nr] : nr
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -803,9 +810,6 @@ void CardReader::presort() {
|
||||||
|
|
||||||
if (sdSort == SD_SORT_NONE) return; //sd sort is turned off
|
if (sdSort == SD_SORT_NONE) return; //sd sort is turned off
|
||||||
|
|
||||||
#if SDSORT_GCODE
|
|
||||||
if (!sort_alpha) return;
|
|
||||||
#endif
|
|
||||||
KEEPALIVE_STATE(IN_HANDLER);
|
KEEPALIVE_STATE(IN_HANDLER);
|
||||||
|
|
||||||
// Throw away old sort index
|
// Throw away old sort index
|
||||||
|
@ -821,177 +825,170 @@ void CardReader::presort() {
|
||||||
lcd_show_fullscreen_message_and_wait_P(_i("Some files will not be sorted. Max. No. of files in 1 folder for sorting is 100."));////MSG_FILE_CNT c=20 r=6
|
lcd_show_fullscreen_message_and_wait_P(_i("Some files will not be sorted. Max. No. of files in 1 folder for sorting is 100."));////MSG_FILE_CNT c=20 r=6
|
||||||
fileCnt = SDSORT_LIMIT;
|
fileCnt = SDSORT_LIMIT;
|
||||||
}
|
}
|
||||||
lcd_clear();
|
|
||||||
#if !SDSORT_USES_RAM
|
|
||||||
lcd_set_progress();
|
|
||||||
#endif
|
|
||||||
lcd_puts_at_P(0, 1, _i("Sorting files"));////MSG_SORTING c=20 r=1
|
|
||||||
|
|
||||||
// Sort order is always needed. May be static or dynamic.
|
|
||||||
#if SDSORT_DYNAMIC_RAM
|
|
||||||
sort_order = new uint8_t[fileCnt];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Use RAM to store the entire directory during pre-sort.
|
|
||||||
// SDSORT_LIMIT should be set to prevent over-allocation.
|
|
||||||
#if SDSORT_USES_RAM
|
|
||||||
|
|
||||||
// If using dynamic ram for names, allocate on the heap.
|
|
||||||
#if SDSORT_CACHE_NAMES
|
|
||||||
#if SDSORT_DYNAMIC_RAM
|
|
||||||
sortshort = new char*[fileCnt];
|
|
||||||
sortnames = new char*[fileCnt];
|
|
||||||
#endif
|
|
||||||
#elif SDSORT_USES_STACK
|
|
||||||
char sortnames[fileCnt][LONG_FILENAME_LENGTH];
|
|
||||||
uint16_t modification_time[fileCnt];
|
|
||||||
uint16_t modification_date[fileCnt];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Folder sorting needs 1 bit per entry for flags.
|
|
||||||
#if HAS_FOLDER_SORTING
|
|
||||||
#if SDSORT_DYNAMIC_RAM
|
|
||||||
isDir = new uint8_t[(fileCnt + 7) >> 3];
|
|
||||||
#elif SDSORT_USES_STACK
|
|
||||||
uint8_t isDir[(fileCnt + 7) >> 3];
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else // !SDSORT_USES_RAM
|
|
||||||
|
|
||||||
uint32_t positions[fileCnt];
|
|
||||||
|
|
||||||
// By default re-read the names from SD for every compare
|
// By default re-read the names from SD for every compare
|
||||||
// retaining only two filenames at a time. This is very
|
// retaining only two filenames at a time. This is very
|
||||||
// slow but is safest and uses minimal RAM.
|
// slow but is safest and uses minimal RAM.
|
||||||
char name1[LONG_FILENAME_LENGTH + 1];
|
char name1[LONG_FILENAME_LENGTH];
|
||||||
uint16_t crmod_time_bckp;
|
uint16_t crmod_time_bckp;
|
||||||
uint16_t crmod_date_bckp;
|
uint16_t crmod_date_bckp;
|
||||||
|
|
||||||
|
#if HAS_FOLDER_SORTING
|
||||||
|
uint16_t dirCnt = 0;
|
||||||
#endif
|
#endif
|
||||||
position = 0;
|
|
||||||
if (fileCnt > 1) {
|
if (fileCnt > 1) {
|
||||||
// Init sort order.
|
// Init sort order.
|
||||||
|
uint8_t sort_order[fileCnt];
|
||||||
for (uint16_t i = 0; i < fileCnt; i++) {
|
for (uint16_t i = 0; i < fileCnt; i++) {
|
||||||
if (!IS_SD_INSERTED) return;
|
if (!IS_SD_INSERTED) return;
|
||||||
manage_heater();
|
manage_heater();
|
||||||
|
if (i == 0)
|
||||||
|
getfilename(0);
|
||||||
|
else
|
||||||
|
getfilename_next(position);
|
||||||
sort_order[i] = i;
|
sort_order[i] = i;
|
||||||
positions[i] = position;
|
sort_positions[i] = position;
|
||||||
getfilename(i);
|
|
||||||
// If using RAM then read all filenames now.
|
|
||||||
#if SDSORT_USES_RAM
|
|
||||||
getfilename(i);
|
|
||||||
#if SDSORT_DYNAMIC_RAM
|
|
||||||
// Use dynamic method to copy long filename
|
|
||||||
sortnames[i] = strdup(LONGEST_FILENAME);
|
|
||||||
#if SDSORT_CACHE_NAMES
|
|
||||||
// When caching also store the short name, since
|
|
||||||
// we're replacing the getfilename() behavior.
|
|
||||||
sortshort[i] = strdup(filename);
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
// Copy filenames into the static array
|
|
||||||
strcpy(sortnames[i], LONGEST_FILENAME);
|
|
||||||
modification_time[i] = crmodTime;
|
|
||||||
modification_date[i] = crmodDate;
|
|
||||||
#if SDSORT_CACHE_NAMES
|
|
||||||
strcpy(sortshort[i], filename);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
// char out[30];
|
|
||||||
// sprintf_P(out, PSTR("---- %i %s %s"), i, filenameIsDir ? "D" : " ", sortnames[i]);
|
|
||||||
// SERIAL_ECHOLN(out);
|
|
||||||
#if HAS_FOLDER_SORTING
|
#if HAS_FOLDER_SORTING
|
||||||
const uint16_t bit = i & 0x07, ind = i >> 3;
|
if (filenameIsDir) dirCnt++;
|
||||||
if (bit == 0) isDir[ind] = 0x00;
|
|
||||||
if (filenameIsDir) isDir[ind] |= _BV(bit);
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef QUICKSORT
|
#ifdef QUICKSORT
|
||||||
quicksort(0, fileCnt - 1);
|
quicksort(0, fileCnt - 1);
|
||||||
#else //Qicksort not defined, use Bubble Sort
|
#elif defined(SHELLSORT)
|
||||||
uint32_t counter = 0;
|
|
||||||
uint16_t total = 0.5*(fileCnt - 1)*(fileCnt);
|
|
||||||
|
|
||||||
// Compare names from the array or just the two buffered names
|
#define _SORT_CMP_NODIR() (strcasecmp(name1, name2) < 0) //true if lowercase(name1) < lowercase(name2)
|
||||||
#if SDSORT_USES_RAM
|
#define _SORT_CMP_TIME_NODIR() (((crmod_date_bckp == crmodDate) && (crmod_time_bckp < crmodTime)) || (crmod_date_bckp < crmodDate))
|
||||||
#define _SORT_CMP_NODIR() (strcasecmp(sortnames[o1], sortnames[o2]) > 0)
|
|
||||||
#define _SORT_CMP_TIME_NODIR() (((modification_date[o1] == modification_date[o2]) && (modification_time[o1] < modification_time[o2])) || \
|
|
||||||
(modification_date[o1] < modification_date [o2]))
|
|
||||||
#else
|
|
||||||
#define _SORT_CMP_NODIR() (strcasecmp(name1, name2) > 0) //true if lowercase(name1) > lowercase(name2)
|
|
||||||
#define _SORT_CMP_TIME_NODIR() (((crmod_date_bckp == crmodDate) && (crmod_time_bckp > crmodTime)) || \
|
|
||||||
(crmod_date_bckp > crmodDate))
|
|
||||||
|
|
||||||
#endif
|
#if HAS_FOLDER_SORTING
|
||||||
|
#define _SORT_CMP_DIR(fs) ((dir1 == filenameIsDir) ? _SORT_CMP_NODIR() : (fs < 0 ? dir1 : !dir1))
|
||||||
|
#define _SORT_CMP_TIME_DIR(fs) ((dir1 == filenameIsDir) ? _SORT_CMP_TIME_NODIR() : (fs < 0 ? dir1 : !dir1))
|
||||||
|
#endif
|
||||||
|
|
||||||
#if HAS_FOLDER_SORTING
|
for (uint8_t runs = 0; runs < 2; runs++)
|
||||||
#if SDSORT_USES_RAM
|
{
|
||||||
// Folder sorting needs an index and bit to test for folder-ness.
|
//run=0: sorts all files and moves folders to the beginning
|
||||||
const uint8_t ind1 = o1 >> 3, bit1 = o1 & 0x07,
|
//run=1: assumes all folders are at the beginning of the list and sorts them
|
||||||
ind2 = o2 >> 3, bit2 = o2 & 0x07;
|
uint16_t sortCountFiles = 0;
|
||||||
#define _SORT_CMP_DIR(fs) \
|
if (runs == 0)
|
||||||
(((isDir[ind1] & _BV(bit1)) != 0) == ((isDir[ind2] & _BV(bit2)) != 0) \
|
{
|
||||||
? _SORT_CMP_NODIR() \
|
sortCountFiles = fileCnt;
|
||||||
: (isDir[fs > 0 ? ind1 : ind2] & (fs > 0 ? _BV(bit1) : _BV(bit2))) != 0)
|
}
|
||||||
#define _SORT_CMP_TIME_DIR(fs) \
|
#if HAS_FOLDER_SORTING
|
||||||
(((isDir[ind1] & _BV(bit1)) != 0) == ((isDir[ind2] & _BV(bit2)) != 0) \
|
else
|
||||||
? _SORT_CMP_TIME_NODIR() \
|
{
|
||||||
: (isDir[fs > 0 ? ind1 : ind2] & (fs > 0 ? _BV(bit1) : _BV(bit2))) != 0)
|
sortCountFiles = dirCnt;
|
||||||
#else
|
}
|
||||||
#define _SORT_CMP_DIR(fs) ((dir1 == filenameIsDir) ? _SORT_CMP_NODIR() : (fs > 0 ? dir1 : !dir1))
|
#endif
|
||||||
#define _SORT_CMP_TIME_DIR(fs) ((dir1 == filenameIsDir) ? _SORT_CMP_TIME_NODIR() : (fs < 0 ? dir1 : !dir1))
|
|
||||||
#endif
|
uint16_t counter = 0;
|
||||||
#endif
|
uint16_t total = 0;
|
||||||
|
for (uint16_t i = sortCountFiles/2; i > 0; i /= 2) total += sortCountFiles - i; //total runs for progress bar
|
||||||
|
menu_progressbar_init(total, (runs == 0)?_i("Sorting files"):_i("Sorting folders"));
|
||||||
|
|
||||||
|
for (uint16_t gap = sortCountFiles/2; gap > 0; gap /= 2)
|
||||||
|
{
|
||||||
|
for (uint16_t i = gap; i < sortCountFiles; i++)
|
||||||
|
{
|
||||||
|
if (!IS_SD_INSERTED) return;
|
||||||
|
|
||||||
|
menu_progressbar_update(counter);
|
||||||
|
counter++;
|
||||||
|
|
||||||
|
manage_heater();
|
||||||
|
uint8_t orderBckp = sort_order[i];
|
||||||
|
getfilename_simple(sort_positions[orderBckp]);
|
||||||
|
strcpy(name1, LONGEST_FILENAME); // save (or getfilename below will trounce it)
|
||||||
|
crmod_date_bckp = crmodDate;
|
||||||
|
crmod_time_bckp = crmodTime;
|
||||||
|
#if HAS_FOLDER_SORTING
|
||||||
|
bool dir1 = filenameIsDir;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint16_t j = i;
|
||||||
|
getfilename_simple(sort_positions[sort_order[j - gap]]);
|
||||||
|
char *name2 = LONGEST_FILENAME; // use the string in-place
|
||||||
|
#if HAS_FOLDER_SORTING
|
||||||
|
while (j >= gap && ((sdSort == SD_SORT_TIME)?_SORT_CMP_TIME_DIR(FOLDER_SORTING):_SORT_CMP_DIR(FOLDER_SORTING)))
|
||||||
|
#else
|
||||||
|
while (j >= gap && ((sdSort == SD_SORT_TIME)?_SORT_CMP_TIME_NODIR():_SORT_CMP_NODIR()))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
sort_order[j] = sort_order[j - gap];
|
||||||
|
j -= gap;
|
||||||
|
#ifdef SORTING_DUMP
|
||||||
|
for (uint16_t z = 0; z < sortCountFiles; z++)
|
||||||
|
{
|
||||||
|
printf_P(PSTR("%2u "), sort_order[z]);
|
||||||
|
}
|
||||||
|
printf_P(PSTR("i%2d j%2d gap%2d orderBckp%2d\n"), i, j, gap, orderBckp);
|
||||||
|
#endif
|
||||||
|
if (j < gap) break;
|
||||||
|
getfilename_simple(sort_positions[sort_order[j - gap]]);
|
||||||
|
name2 = LONGEST_FILENAME; // use the string in-place
|
||||||
|
}
|
||||||
|
sort_order[j] = orderBckp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else //Bubble Sort
|
||||||
|
|
||||||
|
#define _SORT_CMP_NODIR() (strcasecmp(name1, name2) < 0) //true if lowercase(name1) < lowercase(name2)
|
||||||
|
#define _SORT_CMP_TIME_NODIR() (((crmod_date_bckp == crmodDate) && (crmod_time_bckp > crmodTime)) || (crmod_date_bckp > crmodDate))
|
||||||
|
|
||||||
|
#if HAS_FOLDER_SORTING
|
||||||
|
#define _SORT_CMP_DIR(fs) ((dir1 == filenameIsDir) ? _SORT_CMP_NODIR() : (fs < 0 ? dir1 : !dir1))
|
||||||
|
#define _SORT_CMP_TIME_DIR(fs) ((dir1 == filenameIsDir) ? _SORT_CMP_TIME_NODIR() : (fs < 0 ? dir1 : !dir1))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint16_t counter = 0;
|
||||||
|
menu_progressbar_init(0.5*(fileCnt - 1)*(fileCnt), _i("Sorting files"));
|
||||||
|
|
||||||
for (uint16_t i = fileCnt; --i;) {
|
for (uint16_t i = fileCnt; --i;) {
|
||||||
if (!IS_SD_INSERTED) return;
|
if (!IS_SD_INSERTED) return;
|
||||||
bool didSwap = false;
|
bool didSwap = false;
|
||||||
|
|
||||||
#if !SDSORT_USES_RAM //show progresss bar only if slow sorting method is used
|
menu_progressbar_update(counter);
|
||||||
int8_t percent = (counter * 100) / total;//((counter * 100) / pow((fileCnt-1),2));
|
|
||||||
for (int column = 0; column < 20; column++) {
|
|
||||||
if (column < (percent / 5))
|
|
||||||
{
|
|
||||||
lcd_putc_at(column, 2, '\x01'); //simple progress bar
|
|
||||||
}
|
|
||||||
}
|
|
||||||
counter++;
|
counter++;
|
||||||
#endif
|
|
||||||
|
|
||||||
//MYSERIAL.println(int(i));
|
|
||||||
for (uint16_t j = 0; j < i; ++j) {
|
for (uint16_t j = 0; j < i; ++j) {
|
||||||
if (!IS_SD_INSERTED) return;
|
if (!IS_SD_INSERTED) return;
|
||||||
|
#ifdef SORTING_DUMP
|
||||||
|
for (uint16_t z = 0; z < fileCnt; z++)
|
||||||
|
{
|
||||||
|
printf_P(PSTR("%2u "), sort_order[z]);
|
||||||
|
}
|
||||||
|
MYSERIAL.println();
|
||||||
|
#endif
|
||||||
manage_heater();
|
manage_heater();
|
||||||
const uint16_t o1 = sort_order[j], o2 = sort_order[j + 1];
|
const uint16_t o1 = sort_order[j], o2 = sort_order[j + 1];
|
||||||
|
|
||||||
// The most economical method reads names as-needed
|
|
||||||
// throughout the loop. Slow if there are many.
|
|
||||||
#if !SDSORT_USES_RAM
|
|
||||||
counter++;
|
counter++;
|
||||||
getfilename_simple(positions[o1]);
|
getfilename_simple(sort_positions[o1]);
|
||||||
strcpy(name1, LONGEST_FILENAME); // save (or getfilename below will trounce it)
|
strcpy(name1, LONGEST_FILENAME); // save (or getfilename below will trounce it)
|
||||||
crmod_date_bckp = crmodDate;
|
crmod_date_bckp = crmodDate;
|
||||||
crmod_time_bckp = crmodTime;
|
crmod_time_bckp = crmodTime;
|
||||||
#if HAS_FOLDER_SORTING
|
#if HAS_FOLDER_SORTING
|
||||||
bool dir1 = filenameIsDir;
|
bool dir1 = filenameIsDir;
|
||||||
#endif
|
#endif
|
||||||
getfilename_simple(positions[o2]);
|
getfilename_simple(sort_positions[o2]);
|
||||||
char *name2 = LONGEST_FILENAME; // use the string in-place
|
char *name2 = LONGEST_FILENAME; // use the string in-place
|
||||||
|
|
||||||
#endif // !SDSORT_USES_RAM
|
|
||||||
|
|
||||||
// Sort the current pair according to settings.
|
// Sort the current pair according to settings.
|
||||||
if (
|
if (
|
||||||
#if HAS_FOLDER_SORTING
|
#if HAS_FOLDER_SORTING
|
||||||
(sdSort == SD_SORT_TIME && _SORT_CMP_TIME_DIR(FOLDER_SORTING)) || (sdSort == SD_SORT_ALPHA && _SORT_CMP_DIR(FOLDER_SORTING))
|
(sdSort == SD_SORT_TIME && _SORT_CMP_TIME_DIR(FOLDER_SORTING)) || (sdSort == SD_SORT_ALPHA && !_SORT_CMP_DIR(FOLDER_SORTING))
|
||||||
#else
|
#else
|
||||||
(sdSort == SD_SORT_TIME && _SORT_CMP_TIME_NODIR()) || (sdSort == SD_SORT_ALPHA && _SORT_CMP_NODIR())
|
(sdSort == SD_SORT_TIME && _SORT_CMP_TIME_NODIR()) || (sdSort == SD_SORT_ALPHA && !_SORT_CMP_NODIR())
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
#ifdef SORTING_DUMP
|
||||||
|
puts_P(PSTR("swap"));
|
||||||
|
#endif
|
||||||
|
|
||||||
sort_order[j] = o2;
|
sort_order[j] = o2;
|
||||||
sort_order[j + 1] = o1;
|
sort_order[j + 1] = o1;
|
||||||
didSwap = true;
|
didSwap = true;
|
||||||
|
@ -1000,45 +997,45 @@ void CardReader::presort() {
|
||||||
if (!didSwap) break;
|
if (!didSwap) break;
|
||||||
} //end of bubble sort loop
|
} //end of bubble sort loop
|
||||||
#endif
|
#endif
|
||||||
// Using RAM but not keeping names around
|
|
||||||
#if (SDSORT_USES_RAM && !SDSORT_CACHE_NAMES)
|
#ifdef SORTING_DUMP
|
||||||
#if SDSORT_DYNAMIC_RAM
|
for (uint16_t z = 0; z < fileCnt; z++)
|
||||||
for (uint16_t i = 0; i < fileCnt; ++i) free(sortnames[i]);
|
printf_P(PSTR("%2u "), sort_order[z]);
|
||||||
#if HAS_FOLDER_SORTING
|
SERIAL_PROTOCOLLN();
|
||||||
free(isDir);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
uint8_t sort_order_reverse_index[fileCnt];
|
||||||
|
for (uint8_t i = 0; i < fileCnt; i++)
|
||||||
|
sort_order_reverse_index[sort_order[i]] = i;
|
||||||
|
for (uint8_t i = 0; i < fileCnt; i++)
|
||||||
|
{
|
||||||
|
if (sort_order_reverse_index[i] != i)
|
||||||
|
{
|
||||||
|
uint32_t el = sort_positions[i];
|
||||||
|
uint8_t idx = sort_order_reverse_index[i];
|
||||||
|
while (idx != i)
|
||||||
|
{
|
||||||
|
uint32_t el1 = sort_positions[idx];
|
||||||
|
uint8_t idx1 = sort_order_reverse_index[idx];
|
||||||
|
sort_order_reverse_index[idx] = idx;
|
||||||
|
sort_positions[idx] = el;
|
||||||
|
idx = idx1;
|
||||||
|
el = el1;
|
||||||
|
}
|
||||||
|
sort_order_reverse_index[idx] = idx;
|
||||||
|
sort_positions[idx] = el;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
menu_progressbar_finish();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sort_order[0] = 0;
|
|
||||||
#if (SDSORT_USES_RAM && SDSORT_CACHE_NAMES)
|
|
||||||
getfilename(0);
|
getfilename(0);
|
||||||
#if SDSORT_DYNAMIC_RAM
|
sort_positions[0] = position;
|
||||||
sortnames = new char*[1];
|
|
||||||
sortnames[0] = strdup(LONGEST_FILENAME); // malloc
|
|
||||||
sortshort = new char*[1];
|
|
||||||
sortshort[0] = strdup(filename); // malloc
|
|
||||||
isDir = new uint8_t[1];
|
|
||||||
#else
|
|
||||||
strcpy(sortnames[0], LONGEST_FILENAME);
|
|
||||||
strcpy(sortshort[0], filename);
|
|
||||||
#endif
|
|
||||||
isDir[0] = filenameIsDir ? 0x01 : 0x00;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sort_count = fileCnt;
|
sort_count = fileCnt;
|
||||||
}
|
}
|
||||||
#if !SDSORT_USES_RAM //show progresss bar only if slow sorting method is used
|
|
||||||
for (int column = 0; column <= 19; column++)
|
|
||||||
{
|
|
||||||
lcd_putc_at(column, 2, '\x01'); //simple progress bar
|
|
||||||
}
|
|
||||||
_delay(300);
|
|
||||||
lcd_set_degree();
|
|
||||||
lcd_clear();
|
|
||||||
#endif
|
|
||||||
lcd_update(2);
|
lcd_update(2);
|
||||||
KEEPALIVE_STATE(NOT_BUSY);
|
KEEPALIVE_STATE(NOT_BUSY);
|
||||||
lcd_timeoutToStatus.start();
|
lcd_timeoutToStatus.start();
|
||||||
|
@ -1046,17 +1043,6 @@ void CardReader::presort() {
|
||||||
|
|
||||||
void CardReader::flush_presort() {
|
void CardReader::flush_presort() {
|
||||||
if (sort_count > 0) {
|
if (sort_count > 0) {
|
||||||
#if SDSORT_DYNAMIC_RAM
|
|
||||||
delete sort_order;
|
|
||||||
#if SDSORT_CACHE_NAMES
|
|
||||||
for (uint8_t i = 0; i < sort_count; ++i) {
|
|
||||||
free(sortshort[i]); // strdup
|
|
||||||
free(sortnames[i]); // strdup
|
|
||||||
}
|
|
||||||
delete sortshort;
|
|
||||||
delete sortnames;
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
sort_count = 0;
|
sort_count = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ public:
|
||||||
|
|
||||||
void getfilename(uint16_t nr, const char* const match=NULL);
|
void getfilename(uint16_t nr, const char* const match=NULL);
|
||||||
void getfilename_simple(uint32_t position, const char * const match = NULL);
|
void getfilename_simple(uint32_t position, const char * const match = NULL);
|
||||||
|
void getfilename_next(uint32_t position, const char * const match = NULL);
|
||||||
uint16_t getnrfilenames();
|
uint16_t getnrfilenames();
|
||||||
|
|
||||||
void getAbsFilename(char *t);
|
void getAbsFilename(char *t);
|
||||||
|
@ -53,12 +54,7 @@ public:
|
||||||
void swap(uint8_t left, uint8_t right);
|
void swap(uint8_t left, uint8_t right);
|
||||||
void quicksort(uint8_t left, uint8_t right);
|
void quicksort(uint8_t left, uint8_t right);
|
||||||
#endif //SDSORT_QUICKSORT
|
#endif //SDSORT_QUICKSORT
|
||||||
void getfilename_sorted(const uint16_t nr);
|
void getfilename_sorted(const uint16_t nr, uint8_t sdSort);
|
||||||
#if SDSORT_GCODE
|
|
||||||
FORCE_INLINE void setSortOn(bool b) { sort_alpha = b; presort(); }
|
|
||||||
FORCE_INLINE void setSortFolders(int i) { sort_folders = i; presort(); }
|
|
||||||
//FORCE_INLINE void setSortReverse(bool b) { sort_reverse = b; }
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FORCE_INLINE bool isFileOpen() { return file.isOpen(); }
|
FORCE_INLINE bool isFileOpen() { return file.isOpen(); }
|
||||||
|
@ -84,7 +80,7 @@ public:
|
||||||
// There are scenarios when simple modification time is not enough (on MS Windows)
|
// There are scenarios when simple modification time is not enough (on MS Windows)
|
||||||
// Therefore these timestamps hold the most recent one of creation/modification date/times
|
// Therefore these timestamps hold the most recent one of creation/modification date/times
|
||||||
uint16_t crmodTime, crmodDate;
|
uint16_t crmodTime, crmodDate;
|
||||||
uint32_t cluster, position;
|
uint32_t /* cluster, */ position;
|
||||||
char longFilename[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;
|
||||||
|
@ -99,45 +95,7 @@ private:
|
||||||
// Sort files and folders alphabetically.
|
// Sort files and folders alphabetically.
|
||||||
#ifdef SDCARD_SORT_ALPHA
|
#ifdef SDCARD_SORT_ALPHA
|
||||||
uint16_t sort_count; // Count of sorted items in the current directory
|
uint16_t sort_count; // Count of sorted items in the current directory
|
||||||
#if SDSORT_GCODE
|
uint32_t sort_positions[SDSORT_LIMIT];
|
||||||
bool sort_alpha; // Flag to enable / disable the feature
|
|
||||||
int sort_folders; // Flag to enable / disable folder sorting
|
|
||||||
//bool sort_reverse; // Flag to enable / disable reverse sorting
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// By default the sort index is static
|
|
||||||
#if SDSORT_DYNAMIC_RAM
|
|
||||||
uint8_t *sort_order;
|
|
||||||
#else
|
|
||||||
uint8_t sort_order[SDSORT_LIMIT];
|
|
||||||
#endif
|
|
||||||
// Cache filenames to speed up SD menus.
|
|
||||||
#if SDSORT_USES_RAM
|
|
||||||
|
|
||||||
// If using dynamic ram for names, allocate on the heap.
|
|
||||||
#if SDSORT_CACHE_NAMES
|
|
||||||
#if SDSORT_DYNAMIC_RAM
|
|
||||||
char **sortshort, **sortnames;
|
|
||||||
#else
|
|
||||||
char sortshort[SDSORT_LIMIT][FILENAME_LENGTH];
|
|
||||||
char sortnames[SDSORT_LIMIT][FILENAME_LENGTH];
|
|
||||||
#endif
|
|
||||||
#elif !SDSORT_USES_STACK
|
|
||||||
char sortnames[SDSORT_LIMIT][FILENAME_LENGTH];
|
|
||||||
uint16_t modification_time[SDSORT_LIMIT];
|
|
||||||
uint16_t modification_date[SDSORT_LIMIT];
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Folder sorting uses an isDir array when caching items.
|
|
||||||
#if HAS_FOLDER_SORTING
|
|
||||||
#if SDSORT_DYNAMIC_RAM
|
|
||||||
uint8_t *isDir;
|
|
||||||
#elif (SDSORT_CACHE_NAMES) || !(SDSORT_USES_STACK)
|
|
||||||
uint8_t isDir[(SDSORT_LIMIT + 7) >> 3];
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // SDSORT_USES_RAM
|
|
||||||
|
|
||||||
#endif // SDCARD_SORT_ALPHA
|
#endif // SDCARD_SORT_ALPHA
|
||||||
|
|
||||||
|
|
|
@ -963,21 +963,6 @@ void lcd_set_custom_characters_arrows(void)
|
||||||
lcd_createChar_P(1, lcd_chardata_arrdown);
|
lcd_createChar_P(1, lcd_chardata_arrdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t lcd_chardata_progress[8] PROGMEM = {
|
|
||||||
B11111,
|
|
||||||
B11111,
|
|
||||||
B11111,
|
|
||||||
B11111,
|
|
||||||
B11111,
|
|
||||||
B11111,
|
|
||||||
B11111,
|
|
||||||
B11111};
|
|
||||||
|
|
||||||
void lcd_set_custom_characters_progress(void)
|
|
||||||
{
|
|
||||||
lcd_createChar_P(1, lcd_chardata_progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint8_t lcd_chardata_arr2down[8] PROGMEM = {
|
const uint8_t lcd_chardata_arr2down[8] PROGMEM = {
|
||||||
B00000,
|
B00000,
|
||||||
B00000,
|
B00000,
|
||||||
|
|
|
@ -204,7 +204,6 @@ private:
|
||||||
|
|
||||||
extern void lcd_set_custom_characters(void);
|
extern void lcd_set_custom_characters(void);
|
||||||
extern void lcd_set_custom_characters_arrows(void);
|
extern void lcd_set_custom_characters_arrows(void);
|
||||||
extern void lcd_set_custom_characters_progress(void);
|
|
||||||
extern void lcd_set_custom_characters_nextpage(void);
|
extern void lcd_set_custom_characters_nextpage(void);
|
||||||
extern void lcd_set_custom_characters_degree(void);
|
extern void lcd_set_custom_characters_degree(void);
|
||||||
|
|
||||||
|
|
|
@ -34,33 +34,35 @@ uint8_t menu_top = 0;
|
||||||
|
|
||||||
uint8_t menu_clicked = 0;
|
uint8_t menu_clicked = 0;
|
||||||
|
|
||||||
uint8_t menu_entering = 0;
|
|
||||||
uint8_t menu_leaving = 0;
|
uint8_t menu_leaving = 0;
|
||||||
|
|
||||||
menu_func_t menu_menu = 0;
|
menu_func_t menu_menu = 0;
|
||||||
|
|
||||||
static_assert(sizeof(menu_data)>= sizeof(menu_data_edit_t),"menu_data_edit_t doesn't fit into menu_data");
|
static_assert(sizeof(menu_data)>= sizeof(menu_data_edit_t),"menu_data_edit_t doesn't fit into menu_data");
|
||||||
|
|
||||||
|
void menu_data_reset(void)
|
||||||
|
{
|
||||||
|
// Resets the global shared C union.
|
||||||
|
// This ensures, that the menu entered will find out, that it shall initialize itself.
|
||||||
|
memset(&menu_data, 0, sizeof(menu_data));
|
||||||
|
}
|
||||||
|
|
||||||
void menu_goto(menu_func_t menu, const uint32_t encoder, const bool feedback, bool reset_menu_state)
|
void menu_goto(menu_func_t menu, const uint32_t encoder, const bool feedback, bool reset_menu_state)
|
||||||
{
|
{
|
||||||
asm("cli");
|
CRITICAL_SECTION_START;
|
||||||
if (menu_menu != menu)
|
if (menu_menu != menu)
|
||||||
{
|
{
|
||||||
menu_menu = menu;
|
menu_menu = menu;
|
||||||
lcd_encoder = encoder;
|
lcd_encoder = encoder;
|
||||||
menu_top = 0; //reset menu view. Needed if menu_back() is called from deep inside a menu, such as Support
|
menu_top = 0; //reset menu view. Needed if menu_back() is called from deep inside a menu, such as Support
|
||||||
asm("sei");
|
CRITICAL_SECTION_END;
|
||||||
if (reset_menu_state)
|
if (reset_menu_state)
|
||||||
{
|
menu_data_reset();
|
||||||
// Resets the global shared C union.
|
|
||||||
// This ensures, that the menu entered will find out, that it shall initialize itself.
|
|
||||||
memset(&menu_data, 0, sizeof(menu_data));
|
|
||||||
}
|
|
||||||
if (feedback) lcd_quick_feedback();
|
if (feedback) lcd_quick_feedback();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
asm("sei");
|
CRITICAL_SECTION_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
void menu_start(void)
|
void menu_start(void)
|
||||||
|
@ -551,4 +553,33 @@ uint8_t menu_item_edit_P(const char* str, T pval, int16_t min_val, int16_t max_v
|
||||||
template uint8_t menu_item_edit_P<int16_t*>(const char* str, int16_t *pval, int16_t min_val, int16_t max_val);
|
template uint8_t menu_item_edit_P<int16_t*>(const char* str, int16_t *pval, int16_t min_val, int16_t max_val);
|
||||||
template uint8_t menu_item_edit_P<uint8_t*>(const char* str, uint8_t *pval, int16_t min_val, int16_t max_val);
|
template uint8_t menu_item_edit_P<uint8_t*>(const char* str, uint8_t *pval, int16_t min_val, int16_t max_val);
|
||||||
|
|
||||||
#undef _menu_data
|
static uint8_t progressbar_block_count = 0;
|
||||||
|
static uint16_t progressbar_total = 0;
|
||||||
|
void menu_progressbar_init(uint16_t total, const char* title)
|
||||||
|
{
|
||||||
|
lcd_clear();
|
||||||
|
progressbar_block_count = 0;
|
||||||
|
progressbar_total = total;
|
||||||
|
|
||||||
|
lcd_set_cursor(0, 1);
|
||||||
|
lcd_printf_P(PSTR("%-20.20S\n"), title);
|
||||||
|
}
|
||||||
|
|
||||||
|
void menu_progressbar_update(uint16_t newVal)
|
||||||
|
{
|
||||||
|
uint8_t newCnt = (newVal * LCD_WIDTH) / progressbar_total;
|
||||||
|
if (newCnt > LCD_WIDTH)
|
||||||
|
newCnt = LCD_WIDTH;
|
||||||
|
while (newCnt > progressbar_block_count)
|
||||||
|
{
|
||||||
|
lcd_print('\xFF');
|
||||||
|
progressbar_block_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void menu_progressbar_finish(void)
|
||||||
|
{
|
||||||
|
progressbar_total = 1;
|
||||||
|
menu_progressbar_update(1);
|
||||||
|
_delay(300);
|
||||||
|
}
|
||||||
|
|
|
@ -59,13 +59,12 @@ extern uint8_t menu_top;
|
||||||
|
|
||||||
extern uint8_t menu_clicked;
|
extern uint8_t menu_clicked;
|
||||||
|
|
||||||
extern uint8_t menu_entering;
|
|
||||||
extern uint8_t menu_leaving;
|
extern uint8_t menu_leaving;
|
||||||
|
|
||||||
//function pointer to the currently active menu
|
//function pointer to the currently active menu
|
||||||
extern menu_func_t menu_menu;
|
extern menu_func_t menu_menu;
|
||||||
|
|
||||||
|
extern void menu_data_reset(void);
|
||||||
|
|
||||||
extern void menu_goto(menu_func_t menu, const uint32_t encoder, const bool feedback, bool reset_menu_state);
|
extern void menu_goto(menu_func_t menu, const uint32_t encoder, const bool feedback, bool reset_menu_state);
|
||||||
|
|
||||||
|
@ -151,5 +150,8 @@ extern void menu_format_sheet_E(const Sheet &sheet_E, SheetFormatBuffer &buffer)
|
||||||
template <typename T>
|
template <typename T>
|
||||||
extern uint8_t menu_item_edit_P(const char* str, T pval, int16_t min_val, int16_t max_val);
|
extern uint8_t menu_item_edit_P(const char* str, T pval, int16_t min_val, int16_t max_val);
|
||||||
|
|
||||||
|
extern void menu_progressbar_init(uint16_t total, const char* title);
|
||||||
|
extern void menu_progressbar_update(uint16_t newVal);
|
||||||
|
extern void menu_progressbar_finish(void);
|
||||||
|
|
||||||
#endif //_MENU_H
|
#endif //_MENU_H
|
||||||
|
|
|
@ -80,7 +80,7 @@ const char MSG_PRESS_TO_UNLOAD[] PROGMEM_I1 = ISTR("Please press the knob to unl
|
||||||
const char MSG_PRINT_ABORTED[] PROGMEM_I1 = ISTR("Print aborted"); ////c=20
|
const char MSG_PRINT_ABORTED[] PROGMEM_I1 = ISTR("Print aborted"); ////c=20
|
||||||
const char MSG_PULL_OUT_FILAMENT[] PROGMEM_I1 = ISTR("Please pull out filament immediately"); ////c=20 r=4
|
const char MSG_PULL_OUT_FILAMENT[] PROGMEM_I1 = ISTR("Please pull out filament immediately"); ////c=20 r=4
|
||||||
const char MSG_RECOVER_PRINT[] PROGMEM_I1 = ISTR("Blackout occurred. Recover print?"); ////c=20 r=2
|
const char MSG_RECOVER_PRINT[] PROGMEM_I1 = ISTR("Blackout occurred. Recover print?"); ////c=20 r=2
|
||||||
const char MSG_REFRESH[] PROGMEM_I1 = ISTR("\xF8" "Refresh"); ////
|
const char MSG_REFRESH[] PROGMEM_I1 = ISTR("\x04" "Refresh"); ////
|
||||||
const char MSG_REMOVE_STEEL_SHEET[] PROGMEM_I1 = ISTR("Please remove steel sheet from heatbed."); ////c=20 r=4
|
const char MSG_REMOVE_STEEL_SHEET[] PROGMEM_I1 = ISTR("Please remove steel sheet from heatbed."); ////c=20 r=4
|
||||||
const char MSG_RESET[] PROGMEM_I1 = ISTR("Reset"); ////c=14
|
const char MSG_RESET[] PROGMEM_I1 = ISTR("Reset"); ////c=14
|
||||||
const char MSG_RESUME_PRINT[] PROGMEM_I1 = ISTR("Resume print"); ////c=18
|
const char MSG_RESUME_PRINT[] PROGMEM_I1 = ISTR("Resume print"); ////c=18
|
||||||
|
@ -203,4 +203,3 @@ const char MSG_M112_KILL[] PROGMEM_N1 = "M112 called. Emergency Stop."; ////c=20
|
||||||
const char MSG_ADVANCE_K[] PROGMEM_N1 = "Advance K:"; ////c=13
|
const char MSG_ADVANCE_K[] PROGMEM_N1 = "Advance K:"; ////c=13
|
||||||
const char MSG_POWERPANIC_DETECTED[] PROGMEM_N1 = "POWER PANIC DETECTED"; ////c=20
|
const char MSG_POWERPANIC_DETECTED[] PROGMEM_N1 = "POWER PANIC DETECTED"; ////c=20
|
||||||
const char MSG_LCD_STATUS_CHANGED[] PROGMEM_N1 = "LCD status changed";
|
const char MSG_LCD_STATUS_CHANGED[] PROGMEM_N1 = "LCD status changed";
|
||||||
const char MSG_FILE_SELECTED[] PROGMEM_N1 = "File selected"; ////c=20
|
|
||||||
|
|
|
@ -203,7 +203,6 @@ extern const char MSG_M112_KILL[];
|
||||||
extern const char MSG_ADVANCE_K[];
|
extern const char MSG_ADVANCE_K[];
|
||||||
extern const char MSG_POWERPANIC_DETECTED[];
|
extern const char MSG_POWERPANIC_DETECTED[];
|
||||||
extern const char MSG_LCD_STATUS_CHANGED[];
|
extern const char MSG_LCD_STATUS_CHANGED[];
|
||||||
extern const char MSG_FILE_SELECTED[];
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,8 +55,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
int scrollstuff = 0;
|
|
||||||
char longFilenameOLD[LONG_FILENAME_LENGTH];
|
|
||||||
int clock_interval = 0;
|
int clock_interval = 0;
|
||||||
|
|
||||||
static void lcd_sd_updir();
|
static void lcd_sd_updir();
|
||||||
|
@ -64,7 +62,7 @@ static void lcd_mesh_bed_leveling_settings();
|
||||||
static void lcd_backlight_menu();
|
static void lcd_backlight_menu();
|
||||||
|
|
||||||
int8_t ReInitLCD = 0;
|
int8_t ReInitLCD = 0;
|
||||||
|
uint8_t scrollstuff = 0;
|
||||||
|
|
||||||
int8_t SilentModeMenu = SILENT_MODE_OFF;
|
int8_t SilentModeMenu = SILENT_MODE_OFF;
|
||||||
uint8_t SilentModeMenu_MMU = 1; //activate mmu unit stealth mode
|
uint8_t SilentModeMenu_MMU = 1; //activate mmu unit stealth mode
|
||||||
|
@ -326,113 +324,31 @@ bool bSettings; // flag (i.e. 'fake parameter'
|
||||||
|
|
||||||
const char STR_SEPARATOR[] PROGMEM = "------------";
|
const char STR_SEPARATOR[] PROGMEM = "------------";
|
||||||
|
|
||||||
|
static void lcd_implementation_drawmenu_sdfile(uint8_t row, const char* longFilename)
|
||||||
static void lcd_implementation_drawmenu_sdfile_selected(uint8_t row, const char* filename, char* longFilename)
|
|
||||||
{
|
|
||||||
char c;
|
|
||||||
int enc_dif = lcd_encoder_diff / ENCODER_PULSES_PER_STEP;
|
|
||||||
uint8_t n = LCD_WIDTH - 1;
|
|
||||||
|
|
||||||
for(uint_least8_t g = 0; g<4;g++){
|
|
||||||
lcd_putc_at(0, g, ' ');
|
|
||||||
}
|
|
||||||
lcd_putc_at(0, row, '>');
|
|
||||||
|
|
||||||
if (longFilename[0] == '\0')
|
|
||||||
{
|
|
||||||
longFilename = filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
int i = 1;
|
|
||||||
int j = 0;
|
|
||||||
char* longFilenameTMP = longFilename;
|
|
||||||
|
|
||||||
while((c = *longFilenameTMP) != '\0')
|
|
||||||
{
|
|
||||||
lcd_set_cursor(i, row);
|
|
||||||
lcd_print(c);
|
|
||||||
i++;
|
|
||||||
longFilenameTMP++;
|
|
||||||
if(i==LCD_WIDTH){
|
|
||||||
i=1;
|
|
||||||
j++;
|
|
||||||
longFilenameTMP = longFilename + j;
|
|
||||||
n = LCD_WIDTH - 1;
|
|
||||||
for(int g = 0; g<300 ;g++){
|
|
||||||
manage_heater();
|
|
||||||
if(LCD_CLICKED || ( enc_dif != (lcd_encoder_diff / ENCODER_PULSES_PER_STEP))){
|
|
||||||
longFilenameTMP = longFilename;
|
|
||||||
*(longFilenameTMP + LCD_WIDTH - 2) = '\0';
|
|
||||||
i = 1;
|
|
||||||
j = 0;
|
|
||||||
break;
|
|
||||||
}else{
|
|
||||||
if (j == 1) _delay_ms(3); //wait around 1.2 s to start scrolling text
|
|
||||||
_delay_ms(1); //then scroll with redrawing every 300 ms
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(c!='\0'){
|
|
||||||
lcd_putc_at(i, row, c);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
n=n-i+1;
|
|
||||||
lcd_space(n);
|
|
||||||
}
|
|
||||||
static void lcd_implementation_drawmenu_sdfile(uint8_t row, const char* filename, char* longFilename)
|
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
uint8_t n = LCD_WIDTH - 1;
|
uint8_t n = LCD_WIDTH - 1;
|
||||||
lcd_putc_at(0, row, ' ');
|
lcd_set_cursor(0, row);
|
||||||
if (longFilename[0] != '\0')
|
lcd_print((lcd_encoder == menu_item)?'>':' ');
|
||||||
{
|
while( ((c = *longFilename) != '\0') && (n>0) )
|
||||||
filename = longFilename;
|
|
||||||
longFilename[LCD_WIDTH-1] = '\0';
|
|
||||||
}
|
|
||||||
while( ((c = *filename) != '\0') && (n>0) )
|
|
||||||
{
|
{
|
||||||
lcd_print(c);
|
lcd_print(c);
|
||||||
filename++;
|
longFilename++;
|
||||||
n--;
|
n--;
|
||||||
}
|
}
|
||||||
lcd_space(n);
|
lcd_space(n);
|
||||||
}
|
}
|
||||||
static void lcd_implementation_drawmenu_sddirectory_selected(uint8_t row, const char* filename, char* longFilename)
|
static void lcd_implementation_drawmenu_sddirectory(uint8_t row, const char* longFilename)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
uint8_t n = LCD_WIDTH - 2;
|
uint8_t n = LCD_WIDTH - 2;
|
||||||
lcd_putc_at(0, row, '>');
|
lcd_set_cursor(0, row);
|
||||||
lcd_print(LCD_STR_FOLDER[0]);
|
lcd_print((lcd_encoder == menu_item)?'>':' ');
|
||||||
if (longFilename[0] != '\0')
|
lcd_print(LCD_STR_FOLDER[0]);
|
||||||
{
|
while( ((c = *longFilename) != '\0') && (n>0) )
|
||||||
filename = longFilename;
|
|
||||||
longFilename[LCD_WIDTH-2] = '\0';
|
|
||||||
}
|
|
||||||
while( ((c = *filename) != '\0') && (n>0) )
|
|
||||||
{
|
{
|
||||||
lcd_print(c);
|
lcd_print(c);
|
||||||
filename++;
|
longFilename++;
|
||||||
n--;
|
|
||||||
}
|
|
||||||
lcd_space(n);
|
|
||||||
}
|
|
||||||
static void lcd_implementation_drawmenu_sddirectory(uint8_t row, const char* filename, char* longFilename)
|
|
||||||
{
|
|
||||||
char c;
|
|
||||||
uint8_t n = LCD_WIDTH - 2;
|
|
||||||
lcd_putc_at(0, row, ' ');
|
|
||||||
lcd_print(LCD_STR_FOLDER[0]);
|
|
||||||
if (longFilename[0] != '\0')
|
|
||||||
{
|
|
||||||
filename = longFilename;
|
|
||||||
longFilename[LCD_WIDTH-2] = '\0';
|
|
||||||
}
|
|
||||||
while( ((c = *filename) != '\0') && (n>0) )
|
|
||||||
{
|
|
||||||
lcd_print(c);
|
|
||||||
filename++;
|
|
||||||
n--;
|
n--;
|
||||||
}
|
}
|
||||||
lcd_space(n);
|
lcd_space(n);
|
||||||
|
@ -441,48 +357,16 @@ static void lcd_implementation_drawmenu_sddirectory(uint8_t row, const char* fil
|
||||||
|
|
||||||
|
|
||||||
#define MENU_ITEM_SDDIR(str_fn, str_fnl) do { if (menu_item_sddir(str_fn, str_fnl)) return; } while (0)
|
#define MENU_ITEM_SDDIR(str_fn, str_fnl) do { if (menu_item_sddir(str_fn, str_fnl)) return; } while (0)
|
||||||
//#define MENU_ITEM_SDDIR(str, str_fn, str_fnl) MENU_ITEM(sddirectory, str, str_fn, str_fnl)
|
#define MENU_ITEM_SDFILE(str_fn, str_fnl) do { if (menu_item_sdfile(str_fn, str_fnl)) return; } while (0)
|
||||||
//extern uint8_t menu_item_sddir(const char* str, const char* str_fn, char* str_fnl);
|
|
||||||
|
|
||||||
#define MENU_ITEM_SDFILE(str, str_fn, str_fnl) do { if (menu_item_sdfile(str, str_fn, str_fnl)) return; } while (0)
|
|
||||||
//#define MENU_ITEM_SDFILE(str, str_fn, str_fnl) MENU_ITEM(sdfile, str, str_fn, str_fnl)
|
|
||||||
//extern uint8_t menu_item_sdfile(const char* str, const char* str_fn, char* str_fnl);
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t menu_item_sddir(const char* str_fn, char* str_fnl)
|
uint8_t menu_item_sddir(const char* str_fn, char* str_fnl)
|
||||||
{
|
{
|
||||||
#ifdef NEW_SD_MENU
|
|
||||||
// str_fnl[18] = 0;
|
|
||||||
// printf_P(PSTR("menu dir %d '%s' '%s'\n"), menu_row, str_fn, str_fnl);
|
|
||||||
if (menu_item == menu_line)
|
if (menu_item == menu_line)
|
||||||
{
|
{
|
||||||
if (lcd_draw_update)
|
if (lcd_draw_update)
|
||||||
{
|
{
|
||||||
lcd_set_cursor(0, menu_row);
|
lcd_implementation_drawmenu_sddirectory(menu_row, (str_fnl[0] == '\0') ? str_fn : str_fnl);
|
||||||
int cnt = lcd_printf_P(PSTR("%c%c%-18s"), (lcd_encoder == menu_item)?'>':' ', LCD_STR_FOLDER[0], str_fnl[0]?str_fnl:str_fn);
|
|
||||||
// int cnt = lcd_printf_P(PSTR("%c%c%-18s"), (lcd_encoder == menu_item)?'>':' ', LCD_STR_FOLDER[0], str_fn);
|
|
||||||
}
|
|
||||||
if (menu_clicked && (lcd_encoder == menu_item))
|
|
||||||
{
|
|
||||||
uint8_t depth = (uint8_t)card.getWorkDirDepth();
|
|
||||||
strcpy(dir_names[depth], str_fn);
|
|
||||||
// printf_P(PSTR("%s\n"), dir_names[depth]);
|
|
||||||
card.chdir(str_fn);
|
|
||||||
lcd_encoder = 0;
|
|
||||||
return menu_item_ret();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
menu_item++;
|
|
||||||
return 0;
|
|
||||||
#else //NEW_SD_MENU
|
|
||||||
if (menu_item == menu_line)
|
|
||||||
{
|
|
||||||
if (lcd_draw_update)
|
|
||||||
{
|
|
||||||
if (lcd_encoder == menu_item)
|
|
||||||
lcd_implementation_drawmenu_sddirectory_selected(menu_row, str_fn, str_fnl);
|
|
||||||
else
|
|
||||||
lcd_implementation_drawmenu_sddirectory(menu_row, str_fn, str_fnl);
|
|
||||||
}
|
}
|
||||||
if (menu_clicked && (lcd_encoder == menu_item))
|
if (menu_clicked && (lcd_encoder == menu_item))
|
||||||
{
|
{
|
||||||
|
@ -490,80 +374,32 @@ uint8_t menu_item_sddir(const char* str_fn, char* str_fnl)
|
||||||
lcd_update_enabled = 0;
|
lcd_update_enabled = 0;
|
||||||
menu_action_sddirectory(str_fn);
|
menu_action_sddirectory(str_fn);
|
||||||
lcd_update_enabled = 1;
|
lcd_update_enabled = 1;
|
||||||
return menu_item_ret();
|
/* return */ menu_item_ret();
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
menu_item++;
|
menu_item++;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#endif //NEW_SD_MENU
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t menu_item_sdfile(const char*
|
static uint8_t menu_item_sdfile(const char* str_fn, char* str_fnl)
|
||||||
#ifdef NEW_SD_MENU
|
|
||||||
str
|
|
||||||
#endif //NEW_SD_MENU
|
|
||||||
,const char* str_fn, char* str_fnl)
|
|
||||||
{
|
{
|
||||||
#ifdef NEW_SD_MENU
|
|
||||||
// printf_P(PSTR("menu sdfile\n"));
|
|
||||||
// str_fnl[19] = 0;
|
|
||||||
// printf_P(PSTR("menu file %d '%s' '%s'\n"), menu_row, str_fn, str_fnl);
|
|
||||||
if (menu_item == menu_line)
|
if (menu_item == menu_line)
|
||||||
{
|
{
|
||||||
if (lcd_draw_update)
|
if (lcd_draw_update)
|
||||||
{
|
{
|
||||||
// printf_P(PSTR("menu file %d %d '%s'\n"), menu_row, menuData.sdcard_menu.viewState, str_fnl[0]?str_fnl:str_fn);
|
lcd_implementation_drawmenu_sdfile(menu_row, (str_fnl[0] == '\0') ? str_fn : str_fnl);
|
||||||
lcd_set_cursor(0, menu_row);
|
|
||||||
/* if (lcd_encoder == menu_item)
|
|
||||||
{
|
|
||||||
lcd_printf_P(PSTR("%c%-19s"), (lcd_encoder == menu_item)?'>':' ', (str_fnl[0]?str_fnl:str_fn) + 1);
|
|
||||||
if (menuData.sdcard_menu.viewState == 0)
|
|
||||||
{
|
|
||||||
menuData.sdcard_menu.viewState++;
|
|
||||||
lcd_printf_P(PSTR("%c%-19s"), (lcd_encoder == menu_item)?'>':' ', (str_fnl[0]?str_fnl:str_fn) + 1);
|
|
||||||
}
|
|
||||||
else if (menuData.sdcard_menu.viewState == 1)
|
|
||||||
{
|
|
||||||
lcd_printf_P(PSTR("%c%-19s"), (lcd_encoder == menu_item)?'>':' ', (str_fnl[0]?str_fnl:str_fn) + 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else*/
|
|
||||||
{
|
|
||||||
str_fnl[19] = 0;
|
|
||||||
lcd_printf_P(PSTR("%c%-19s"), (lcd_encoder == menu_item)?'>':' ', str_fnl[0]?str_fnl:str_fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
// int cnt = lcd_printf_P(PSTR("%c%-19s"), (lcd_encoder == menu_item)?'>':' ', str_fnl);
|
|
||||||
// int cnt = lcd_printf_P(PSTR("%cTESTIK.gcode"), (lcd_encoder == menu_item)?'>':' ');
|
|
||||||
}
|
}
|
||||||
if (menu_clicked && (lcd_encoder == menu_item))
|
if (menu_clicked && (lcd_encoder == menu_item))
|
||||||
{
|
{
|
||||||
return menu_item_ret();
|
lcd_consume_click();
|
||||||
}
|
|
||||||
}
|
|
||||||
menu_item++;
|
|
||||||
return 0;
|
|
||||||
#else //NEW_SD_MENU
|
|
||||||
if (menu_item == menu_line)
|
|
||||||
{
|
|
||||||
if (lcd_draw_update)
|
|
||||||
{
|
|
||||||
if (lcd_encoder == menu_item)
|
|
||||||
lcd_implementation_drawmenu_sdfile_selected(menu_row, str_fn, str_fnl);
|
|
||||||
else
|
|
||||||
lcd_implementation_drawmenu_sdfile(menu_row, str_fn, str_fnl);
|
|
||||||
}
|
|
||||||
if (menu_clicked && (lcd_encoder == menu_item))
|
|
||||||
{
|
|
||||||
lcd_consume_click();
|
|
||||||
menu_action_sdfile(str_fn);
|
menu_action_sdfile(str_fn);
|
||||||
return menu_item_ret();
|
/* return */ menu_item_ret();
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
menu_item++;
|
menu_item++;
|
||||||
return 0;
|
return 0;
|
||||||
#endif //NEW_SD_MENU
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print temperature (nozzle/bed) (9 chars total)
|
// Print temperature (nozzle/bed) (9 chars total)
|
||||||
|
@ -735,14 +571,6 @@ void lcdui_print_time(void)
|
||||||
//! @Brief Print status line on status screen
|
//! @Brief Print status line on status screen
|
||||||
void lcdui_print_status_line(void)
|
void lcdui_print_status_line(void)
|
||||||
{
|
{
|
||||||
if (IS_SD_PRINTING) {
|
|
||||||
if (strcmp(longFilenameOLD, (card.longFilename[0] ? card.longFilename : card.filename)) != 0) {
|
|
||||||
memset(longFilenameOLD, '\0', strlen(longFilenameOLD));
|
|
||||||
sprintf_P(longFilenameOLD, PSTR("%s"), (card.longFilename[0] ? card.longFilename : card.filename));
|
|
||||||
scrollstuff = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (heating_status) { // If heating flag, show progress of heating
|
if (heating_status) { // If heating flag, show progress of heating
|
||||||
heating_status_counter++;
|
heating_status_counter++;
|
||||||
if (heating_status_counter > 13) {
|
if (heating_status_counter > 13) {
|
||||||
|
@ -776,6 +604,7 @@ void lcdui_print_status_line(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((IS_SD_PRINTING) && (custom_message_type == CustomMsg::Status)) { // If printing from SD, show what we are printing
|
else if ((IS_SD_PRINTING) && (custom_message_type == CustomMsg::Status)) { // If printing from SD, show what we are printing
|
||||||
|
const char* longFilenameOLD = (card.longFilename[0] ? card.longFilename : card.filename);
|
||||||
if(strlen(longFilenameOLD) > LCD_WIDTH) {
|
if(strlen(longFilenameOLD) > LCD_WIDTH) {
|
||||||
int inters = 0;
|
int inters = 0;
|
||||||
int gh = scrollstuff;
|
int gh = scrollstuff;
|
||||||
|
@ -4196,7 +4025,7 @@ static void prusa_stat_printinfo()
|
||||||
SERIAL_ECHOPGM("][FEM:");
|
SERIAL_ECHOPGM("][FEM:");
|
||||||
SERIAL_ECHO(itostr3(feedmultiply));
|
SERIAL_ECHO(itostr3(feedmultiply));
|
||||||
SERIAL_ECHOPGM("][FNM:");
|
SERIAL_ECHOPGM("][FNM:");
|
||||||
SERIAL_ECHO(longFilenameOLD);
|
SERIAL_ECHO(card.longFilename[0] ? card.longFilename : card.filename);
|
||||||
SERIAL_ECHOPGM("][TIM:");
|
SERIAL_ECHOPGM("][TIM:");
|
||||||
if (starttime != 0)
|
if (starttime != 0)
|
||||||
{
|
{
|
||||||
|
@ -4511,17 +4340,10 @@ static void lcd_fsensor_state_set()
|
||||||
}
|
}
|
||||||
#endif //FILAMENT_SENSOR
|
#endif //FILAMENT_SENSOR
|
||||||
|
|
||||||
|
|
||||||
#if !SDSORT_USES_RAM
|
|
||||||
void lcd_set_degree() {
|
void lcd_set_degree() {
|
||||||
lcd_set_custom_characters_degree();
|
lcd_set_custom_characters_degree();
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcd_set_progress() {
|
|
||||||
lcd_set_custom_characters_progress();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (LANG_MODE != 0)
|
#if (LANG_MODE != 0)
|
||||||
|
|
||||||
void menu_setlang(unsigned char lang)
|
void menu_setlang(unsigned char lang)
|
||||||
|
@ -7166,17 +6988,25 @@ static void lcd_control_temperature_menu()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if SDCARDDETECT == -1
|
|
||||||
static void lcd_sd_refresh()
|
static void lcd_sd_refresh()
|
||||||
{
|
{
|
||||||
|
#if SDCARDDETECT == -1
|
||||||
card.initsd();
|
card.initsd();
|
||||||
menu_top = 0;
|
#else
|
||||||
}
|
card.presort();
|
||||||
#endif
|
#endif
|
||||||
|
menu_top = 0;
|
||||||
|
lcd_encoder = 0;
|
||||||
|
menu_data_reset(); //Forces reloading of cached variables.
|
||||||
|
}
|
||||||
|
|
||||||
static void lcd_sd_updir()
|
static void lcd_sd_updir()
|
||||||
{
|
{
|
||||||
card.updir();
|
card.updir();
|
||||||
menu_top = 0;
|
menu_top = 0;
|
||||||
|
lcd_encoder = 0;
|
||||||
|
menu_data_reset(); //Forces reloading of cached variables.
|
||||||
}
|
}
|
||||||
|
|
||||||
void lcd_print_stop()
|
void lcd_print_stop()
|
||||||
|
@ -7272,57 +7102,156 @@ void lcd_sdcard_stop()
|
||||||
|
|
||||||
void lcd_sdcard_menu()
|
void lcd_sdcard_menu()
|
||||||
{
|
{
|
||||||
uint8_t sdSort = eeprom_read_byte((uint8_t*)EEPROM_SD_SORT);
|
enum menuState_t : uint8_t {_uninitialized, _standard, _scrolling};
|
||||||
|
typedef struct
|
||||||
if (card.presort_flag == true) {
|
{
|
||||||
card.presort_flag = false;
|
menuState_t menuState = _uninitialized;
|
||||||
card.presort();
|
uint8_t offset;
|
||||||
}
|
bool isDir;
|
||||||
if (lcd_draw_update == 0 && LCD_CLICKED == 0)
|
const char* scrollPointer;
|
||||||
//_delay(100);
|
uint16_t selectedFileID;
|
||||||
return; // nothing to do (so don't thrash the SD card)
|
uint16_t fileCnt;
|
||||||
uint16_t fileCnt = card.getnrfilenames();
|
int8_t row;
|
||||||
|
uint8_t sdSort;
|
||||||
|
ShortTimer lcd_scrollTimer;
|
||||||
MENU_BEGIN();
|
} _menu_data_sdcard_t;
|
||||||
MENU_ITEM_BACK_P(_T(bMain?MSG_MAIN:MSG_BACK)); // i.e. default menu-item / menu-item after card insertion
|
static_assert(sizeof(menu_data)>= sizeof(_menu_data_sdcard_t),"_menu_data_sdcard_t doesn't fit into menu_data");
|
||||||
card.getWorkDirName();
|
_menu_data_sdcard_t* _md = (_menu_data_sdcard_t*)&(menu_data[0]);
|
||||||
if (card.filename[0] == '/')
|
|
||||||
{
|
switch(_md->menuState)
|
||||||
#if SDCARDDETECT == -1
|
{
|
||||||
MENU_ITEM_FUNCTION_P(_T(MSG_REFRESH), lcd_sd_refresh);
|
case _uninitialized: //Initialize menu data
|
||||||
#endif
|
{
|
||||||
} else {
|
if (card.presort_flag == true) //used to force resorting if sorting type is changed.
|
||||||
MENU_ITEM_FUNCTION_P(PSTR(LCD_STR_FOLDER ".."), lcd_sd_updir);
|
{
|
||||||
}
|
card.presort_flag = false;
|
||||||
|
card.presort();
|
||||||
for (uint16_t i = 0; i < fileCnt; i++)
|
}
|
||||||
{
|
_md->fileCnt = card.getnrfilenames();
|
||||||
if (menu_item == menu_line)
|
_md->sdSort = eeprom_read_byte((uint8_t*)EEPROM_SD_SORT);
|
||||||
{
|
_md->menuState = _standard;
|
||||||
const uint16_t nr = ((sdSort == SD_SORT_NONE) || farm_mode || (sdSort == SD_SORT_TIME)) ? (fileCnt - 1 - i) : i;
|
// FALLTHRU
|
||||||
/*#ifdef SDCARD_RATHERRECENTFIRST
|
}
|
||||||
#ifndef SDCARD_SORT_ALPHA
|
case _standard: //normal menu structure.
|
||||||
fileCnt - 1 -
|
{
|
||||||
#endif
|
if (!_md->lcd_scrollTimer.running()) //if the timer is not running, then the menu state was just switched, so redraw the screen.
|
||||||
#endif
|
{
|
||||||
i;*/
|
_md->lcd_scrollTimer.start();
|
||||||
#ifdef SDCARD_SORT_ALPHA
|
lcd_draw_update = 1;
|
||||||
if (sdSort == SD_SORT_NONE) card.getfilename(nr);
|
}
|
||||||
else card.getfilename_sorted(nr);
|
if (_md->lcd_scrollTimer.expired(500) && (_md->row != -1)) //switch to the scrolling state on timeout if a file/dir is selected.
|
||||||
#else
|
{
|
||||||
card.getfilename(nr);
|
_md->menuState = _scrolling;
|
||||||
#endif
|
_md->offset = 0;
|
||||||
|
_md->scrollPointer = NULL;
|
||||||
|
_md->lcd_scrollTimer.start();
|
||||||
|
lcd_draw_update = 1; //forces last load before switching to scrolling.
|
||||||
|
}
|
||||||
|
if (lcd_draw_update == 0 && !LCD_CLICKED)
|
||||||
|
return; // nothing to do (so don't thrash the SD card)
|
||||||
|
|
||||||
if (card.filenameIsDir)
|
_md->row = -1; // assume that no SD file/dir is currently selected. Once they are rendered, it will be changed to the correct row for the _scrolling state.
|
||||||
MENU_ITEM_SDDIR(card.filename, card.longFilename);
|
|
||||||
else
|
//if we reached this point it means that the encoder moved or clicked or the state is being switched. Reset the scrollTimer.
|
||||||
MENU_ITEM_SDFILE(_T(MSG_CARD_MENU), card.filename, card.longFilename);
|
_md->lcd_scrollTimer.start();
|
||||||
} else {
|
|
||||||
MENU_ITEM_DUMMY();
|
MENU_BEGIN();
|
||||||
}
|
MENU_ITEM_BACK_P(_T(bMain?MSG_MAIN:MSG_BACK)); // i.e. default menu-item / menu-item after card insertion
|
||||||
}
|
card.getWorkDirName();
|
||||||
MENU_END();
|
if (card.filename[0] == '/')
|
||||||
|
{
|
||||||
|
#if SDCARDDETECT == -1
|
||||||
|
MENU_ITEM_FUNCTION_P(_T(MSG_REFRESH), lcd_sd_refresh);
|
||||||
|
#else
|
||||||
|
if (card.ToshibaFlashAir_isEnabled())
|
||||||
|
MENU_ITEM_FUNCTION_P(_T(MSG_REFRESH), lcd_sd_refresh); //show the refresh option if in flashAir mode.
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
MENU_ITEM_FUNCTION_P(PSTR(LCD_STR_FOLDER ".."), lcd_sd_updir); //Show the updir button if in a subdir.
|
||||||
|
|
||||||
|
for (uint16_t i = _md->fileCnt; i-- > 0;) // Every file, from top to bottom.
|
||||||
|
{
|
||||||
|
if (menu_item == menu_line) //If the file is on the screen.
|
||||||
|
{
|
||||||
|
//load filename to memory.
|
||||||
|
#ifdef SDCARD_SORT_ALPHA
|
||||||
|
if (_md->sdSort == SD_SORT_NONE)
|
||||||
|
card.getfilename(i);
|
||||||
|
else
|
||||||
|
card.getfilename_sorted(i, _md->sdSort);
|
||||||
|
#else
|
||||||
|
card.getfilename(i);
|
||||||
|
#endif
|
||||||
|
if (lcd_encoder == menu_item) //If the file is selected.
|
||||||
|
{
|
||||||
|
|
||||||
|
_md->selectedFileID = i;
|
||||||
|
_md->isDir = card.filenameIsDir;
|
||||||
|
_md->row = menu_row;
|
||||||
|
}
|
||||||
|
if (card.filenameIsDir)
|
||||||
|
MENU_ITEM_SDDIR(card.filename, card.longFilename);
|
||||||
|
else
|
||||||
|
MENU_ITEM_SDFILE(card.filename, card.longFilename);
|
||||||
|
}
|
||||||
|
else MENU_ITEM_DUMMY(); //dummy item that just increments the internal menu counters.
|
||||||
|
}
|
||||||
|
MENU_END();
|
||||||
|
} break;
|
||||||
|
case _scrolling: //scrolling filename
|
||||||
|
{
|
||||||
|
const bool rewindFlag = LCD_CLICKED || lcd_draw_update; //flag that says whether the menu should return to _standard state.
|
||||||
|
|
||||||
|
if (_md->scrollPointer == NULL)
|
||||||
|
{
|
||||||
|
//load filename to memory.
|
||||||
|
#ifdef SDCARD_SORT_ALPHA
|
||||||
|
if (_md->sdSort == SD_SORT_NONE)
|
||||||
|
card.getfilename(_md->selectedFileID);
|
||||||
|
else
|
||||||
|
card.getfilename_sorted(_md->selectedFileID, _md->sdSort);
|
||||||
|
#else
|
||||||
|
card.getfilename(_md->selectedFileID);
|
||||||
|
#endif
|
||||||
|
_md->scrollPointer = (card.longFilename[0] == '\0') ? card.filename : card.longFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rewindFlag == 1)
|
||||||
|
_md->offset = 0; //redraw once again from the beginning.
|
||||||
|
if (_md->lcd_scrollTimer.expired(300) || rewindFlag)
|
||||||
|
{
|
||||||
|
uint8_t i = LCD_WIDTH - ((_md->isDir)?2:1);
|
||||||
|
lcd_set_cursor(0, _md->row);
|
||||||
|
lcd_print('>');
|
||||||
|
if (_md->isDir)
|
||||||
|
lcd_print(LCD_STR_FOLDER[0]);
|
||||||
|
for (; i != 0; i--)
|
||||||
|
{
|
||||||
|
const char* c = (_md->scrollPointer + _md->offset + ((LCD_WIDTH - ((_md->isDir)?2:1)) - i));
|
||||||
|
lcd_print(c[0]);
|
||||||
|
if (c[1])
|
||||||
|
_md->lcd_scrollTimer.start();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_md->lcd_scrollTimer.stop();
|
||||||
|
break; //stop at the end of the string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i != 0) //adds spaces if string is incomplete or at the end (instead of null).
|
||||||
|
{
|
||||||
|
lcd_space(i);
|
||||||
|
}
|
||||||
|
_md->offset++;
|
||||||
|
}
|
||||||
|
if (rewindFlag) //go back to sd_menu.
|
||||||
|
{
|
||||||
|
_md->lcd_scrollTimer.stop(); //forces redraw in _standard state
|
||||||
|
_md->menuState = _standard;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
default: _md->menuState = _uninitialized; //shouldn't ever happen. Anyways, initialize the menu.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#ifdef TMC2130
|
#ifdef TMC2130
|
||||||
static void lcd_belttest_v()
|
static void lcd_belttest_v()
|
||||||
|
@ -8577,7 +8506,6 @@ static bool check_file(const char* filename) {
|
||||||
const uint32_t filesize = card.getFileSize();
|
const uint32_t filesize = card.getFileSize();
|
||||||
uint32_t startPos = 0;
|
uint32_t startPos = 0;
|
||||||
const uint16_t bytesToCheck = min(END_FILE_SECTION, filesize);
|
const uint16_t bytesToCheck = min(END_FILE_SECTION, filesize);
|
||||||
uint8_t blocksPrinted = 0;
|
|
||||||
if (filesize > END_FILE_SECTION) {
|
if (filesize > END_FILE_SECTION) {
|
||||||
startPos = filesize - END_FILE_SECTION;
|
startPos = filesize - END_FILE_SECTION;
|
||||||
card.setIndex(startPos);
|
card.setIndex(startPos);
|
||||||
|
@ -8585,22 +8513,15 @@ static bool check_file(const char* filename) {
|
||||||
cmdqueue_reset();
|
cmdqueue_reset();
|
||||||
cmdqueue_serial_disabled = true;
|
cmdqueue_serial_disabled = true;
|
||||||
|
|
||||||
lcd_clear();
|
menu_progressbar_init(bytesToCheck, _i("Checking file"));
|
||||||
lcd_puts_at_P(0, 1, _i("Checking file"));////c=20 r=1
|
|
||||||
lcd_set_cursor(0, 2);
|
|
||||||
while (!card.eof() && !result) {
|
while (!card.eof() && !result) {
|
||||||
for (; blocksPrinted < (((card.get_sdpos() - startPos) * LCD_WIDTH) / bytesToCheck); blocksPrinted++)
|
menu_progressbar_update(card.get_sdpos() - startPos);
|
||||||
lcd_print('\xFF'); //simple progress bar
|
|
||||||
|
|
||||||
card.sdprinting = true;
|
card.sdprinting = true;
|
||||||
get_command();
|
get_command();
|
||||||
result = check_commands();
|
result = check_commands();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; blocksPrinted < LCD_WIDTH; blocksPrinted++)
|
menu_progressbar_finish();
|
||||||
lcd_print('\xFF'); //simple progress bar
|
|
||||||
_delay(100); //for the user to see the end of the progress bar.
|
|
||||||
|
|
||||||
|
|
||||||
cmdqueue_serial_disabled = false;
|
cmdqueue_serial_disabled = false;
|
||||||
card.printingHasFinished();
|
card.printingHasFinished();
|
||||||
|
@ -8659,6 +8580,7 @@ void menu_action_sddirectory(const char* filename)
|
||||||
{
|
{
|
||||||
card.chdir(filename, true);
|
card.chdir(filename, true);
|
||||||
lcd_encoder = 0;
|
lcd_encoder = 0;
|
||||||
|
menu_data_reset(); //Forces reloading of cached variables.
|
||||||
}
|
}
|
||||||
|
|
||||||
/** LCD API **/
|
/** LCD API **/
|
||||||
|
@ -8723,7 +8645,6 @@ static void lcd_connect_printer() {
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int t = 0;
|
int t = 0;
|
||||||
lcd_set_custom_characters_progress();
|
|
||||||
lcd_puts_at_P(0, 0, _i("Connect printer to"));
|
lcd_puts_at_P(0, 0, _i("Connect printer to"));
|
||||||
lcd_puts_at_P(0, 1, _i("monitoring or hold"));
|
lcd_puts_at_P(0, 1, _i("monitoring or hold"));
|
||||||
lcd_puts_at_P(0, 2, _i("the knob to continue"));
|
lcd_puts_at_P(0, 2, _i("the knob to continue"));
|
||||||
|
@ -8740,12 +8661,11 @@ static void lcd_connect_printer() {
|
||||||
i = 0;
|
i = 0;
|
||||||
lcd_puts_at_P(0, 3, PSTR(" "));
|
lcd_puts_at_P(0, 3, PSTR(" "));
|
||||||
}
|
}
|
||||||
if (i!=0) lcd_puts_at_P((i * 20) / (NC_BUTTON_LONG_PRESS * 10), 3, "\x01");
|
if (i!=0) lcd_puts_at_P((i * 20) / (NC_BUTTON_LONG_PRESS * 10), 3, "\xFF");
|
||||||
if (i == NC_BUTTON_LONG_PRESS * 10) {
|
if (i == NC_BUTTON_LONG_PRESS * 10) {
|
||||||
no_response = false;
|
no_response = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lcd_set_custom_characters_degree();
|
|
||||||
lcd_update_enable(true);
|
lcd_update_enable(true);
|
||||||
lcd_update(2);
|
lcd_update(2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,6 +155,8 @@ extern uint8_t SilentModeMenu_MMU;
|
||||||
extern bool cancel_heatup;
|
extern bool cancel_heatup;
|
||||||
extern bool isPrintPaused;
|
extern bool isPrintPaused;
|
||||||
|
|
||||||
|
extern uint8_t scrollstuff;
|
||||||
|
|
||||||
|
|
||||||
void lcd_ignore_click(bool b=true);
|
void lcd_ignore_click(bool b=true);
|
||||||
void lcd_commands();
|
void lcd_commands();
|
||||||
|
@ -228,10 +230,7 @@ void lcd_temp_calibration_set();
|
||||||
|
|
||||||
void display_loading();
|
void display_loading();
|
||||||
|
|
||||||
#if !SDSORT_USES_RAM
|
|
||||||
void lcd_set_degree();
|
void lcd_set_degree();
|
||||||
void lcd_set_progress();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (LANG_MODE != 0)
|
#if (LANG_MODE != 0)
|
||||||
void lcd_language();
|
void lcd_language();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue