Browse Source

Merge branch 'MK3_revised_filename_scrolling' into MK3_NEW_SD_COMPILATION

Alex Voinea 4 years ago
parent
commit
37dc5fed45
8 changed files with 159 additions and 372 deletions
  1. 22 123
      Firmware/cardreader.cpp
  2. 2 33
      Firmware/cardreader.h
  3. 1 0
      Firmware/lcd.cpp
  4. 2 0
      Firmware/lcd.h
  5. 20 0
      Firmware/menu.cpp
  6. 4 0
      Firmware/menu.h
  7. 106 216
      Firmware/ultralcd.cpp
  8. 2 0
      Firmware/ultralcd.h

+ 22 - 123
Firmware/cardreader.cpp

@@ -416,6 +416,7 @@ void CardReader::openFile(const char* name,bool read, bool replace_current/*=tru
       getfilename(0, fname);
       lcd_setstatus(longFilename[0] ? longFilename : fname);
       lcd_setstatus("SD-PRINTING         ");
+      scrollstuff = 0;
     }
     else
     {
@@ -689,12 +690,20 @@ void CardReader::updir()
 * Get the name of a file in the current directory by sort-index
 */
 void CardReader::getfilename_sorted(const uint16_t nr) {
-	getfilename(
-	#if SDSORT_GCODE
-		sort_alpha &&
-	#endif
-		(nr < sort_count) ? sort_order[nr] : nr
-	);
+	if (nr < sort_count)
+        getfilename_simple(
+        #if SDSORT_GCODE
+            sort_alpha &&
+        #endif
+            sort_positions[sort_order[nr]]
+        );
+    else
+        getfilename(
+        #if SDSORT_GCODE
+            sort_alpha &&
+        #endif
+            nr
+        );
 }
 
 /**
@@ -730,44 +739,10 @@ void CardReader::presort() {
 			fileCnt = SDSORT_LIMIT;
 		}
 		lcd_clear();
-		#if !SDSORT_USES_RAM
-			lcd_set_progress();
-		#endif
+        lcd_set_progress();
 		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];
+		// uint32_t positions[fileCnt];
 
 		// By default re-read the names from SD for every compare
 		// retaining only two filenames at a time. This is very
@@ -776,7 +751,6 @@ void CardReader::presort() {
 		uint16_t modification_time_bckp;
 		uint16_t modification_date_bckp;
 
-		#endif
 		position = 0;
 		if (fileCnt > 1) {
 			// Init sort order.
@@ -784,37 +758,8 @@ void CardReader::presort() {
 				if (!IS_SD_INSERTED) return;
 				manage_heater();
 				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] = modificationTime;
-				modification_date[i] = modificationDate;
-				#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
-				const uint16_t bit = i & 0x07, ind = i >> 3;
-				if (bit == 0) isDir[ind] = 0x00;
-				if (filenameIsDir) isDir[ind] |= _BV(bit);
-				#endif
-				#endif
 			}
 
 #ifdef QUICKSORT
@@ -824,41 +769,18 @@ void CardReader::presort() {
 			uint16_t total = 0.5*(fileCnt - 1)*(fileCnt);
 
 			// Compare names from the array or just the two buffered names
-			#if SDSORT_USES_RAM
-			#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() (((modification_date_bckp == modificationDate) && (modification_time_bckp > modificationTime)) || \
-																	(modification_date_bckp > modificationDate))
-
-			#endif
+			#define _SORT_CMP_TIME_NODIR() (((modification_date_bckp == modificationDate) && (modification_time_bckp > modificationTime)) || (modification_date_bckp > modificationDate))
 
 			#if HAS_FOLDER_SORTING
-			#if SDSORT_USES_RAM
-			// Folder sorting needs an index and bit to test for folder-ness.
-			const uint8_t ind1 = o1 >> 3, bit1 = o1 & 0x07,
-				ind2 = o2 >> 3, bit2 = o2 & 0x07;
-			#define _SORT_CMP_DIR(fs) \
-										  (((isDir[ind1] & _BV(bit1)) != 0) == ((isDir[ind2] & _BV(bit2)) != 0) \
-											? _SORT_CMP_NODIR() \
-											: (isDir[fs > 0 ? ind1 : ind2] & (fs > 0 ? _BV(bit1) : _BV(bit2))) != 0)
-			#define _SORT_CMP_TIME_DIR(fs) \
-										  (((isDir[ind1] & _BV(bit1)) != 0) == ((isDir[ind2] & _BV(bit2)) != 0) \
-											? _SORT_CMP_TIME_NODIR() \
-											: (isDir[fs > 0 ? ind1 : ind2] & (fs > 0 ? _BV(bit1) : _BV(bit2))) != 0)
-			#else
 			#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
-			#endif
 
 			for (uint16_t i = fileCnt; --i;) {
 				if (!IS_SD_INSERTED) return;
 				bool didSwap = false;
 
-				#if !SDSORT_USES_RAM //show progresss bar only if slow sorting method is used
 				int8_t percent = (counter * 100) / total;//((counter * 100) / pow((fileCnt-1),2));
 				for (int column = 0; column < 20; column++) {
 					if (column < (percent / 5))
@@ -868,7 +790,6 @@ void CardReader::presort() {
 					}
 				}
 				counter++;
-				#endif
 
 				//MYSERIAL.println(int(i));
 				for (uint16_t j = 0; j < i; ++j) {
@@ -880,14 +801,14 @@ void CardReader::presort() {
 					// throughout the loop. Slow if there are many.
 					#if !SDSORT_USES_RAM
 					counter++;
-					getfilename_simple(positions[o1]);
+					getfilename_simple(sort_positions[o1]);
 					strcpy(name1, LONGEST_FILENAME); // save (or getfilename below will trounce it)
 					modification_date_bckp = modificationDate;
 					modification_time_bckp = modificationTime;
 					#if HAS_FOLDER_SORTING
 					bool dir1 = filenameIsDir;
 					#endif
-					getfilename_simple(positions[o2]);
+					getfilename_simple(sort_positions[o2]);
 					char *name2 = LONGEST_FILENAME; // use the string in-place
 
 					#endif // !SDSORT_USES_RAM
@@ -909,32 +830,9 @@ void CardReader::presort() {
 				if (!didSwap) break;
 			} //end of bubble sort loop
 #endif
-			  // Using RAM but not keeping names around
-			#if (SDSORT_USES_RAM && !SDSORT_CACHE_NAMES)
-			#if SDSORT_DYNAMIC_RAM
-			for (uint16_t i = 0; i < fileCnt; ++i) free(sortnames[i]);
-			#if HAS_FOLDER_SORTING
-			free(isDir);
-			#endif
-			#endif
-			#endif
 		}
 		else {
 			sort_order[0] = 0;
-		#if (SDSORT_USES_RAM && SDSORT_CACHE_NAMES)
-			getfilename(0);
-			#if SDSORT_DYNAMIC_RAM
-			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;
@@ -949,6 +847,7 @@ void CardReader::presort() {
 	lcd_set_degree();
 	lcd_clear();
 #endif
+	lcd_scrollTimer.start();
 	lcd_update(2);
 	KEEPALIVE_STATE(NOT_BUSY);
 	lcd_timeoutToStatus.start();

+ 2 - 33
Firmware/cardreader.h

@@ -93,39 +93,8 @@ private:
 							//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
+  uint8_t sort_order[SDSORT_LIMIT]; // By default the sort index is static.
+  uint32_t sort_positions[SDSORT_LIMIT];
 
 #endif // SDCARD_SORT_ALPHA
 

+ 1 - 0
Firmware/lcd.cpp

@@ -645,6 +645,7 @@ lcd_lcdupdate_func_t lcd_lcdupdate_func = 0;
 static ShortTimer buttonBlanking;
 ShortTimer longPressTimer;
 LongTimer lcd_timeoutToStatus;
+ShortTimer lcd_scrollTimer;
 
 
 //! @brief Was button clicked?

+ 2 - 0
Firmware/lcd.h

@@ -102,6 +102,8 @@ extern uint8_t lcd_update_enabled;
 
 extern LongTimer lcd_timeoutToStatus;
 
+extern ShortTimer lcd_scrollTimer;
+
 extern uint32_t lcd_next_update_millis;
 
 extern uint8_t lcd_status_update_delay;

+ 20 - 0
Firmware/menu.cpp

@@ -55,6 +55,7 @@ void menu_goto(menu_func_t menu, const uint32_t encoder, const bool feedback, bo
 			// This ensures, that the menu entered will find out, that it shall initialize itself.
 			memset(&menu_data, 0, sizeof(menu_data));
 		}
+		menu_entering = 1; //next menu that supports entering will clear this flag on first enter. Used for initializing some menus only one time.
 		if (feedback) lcd_quick_feedback();
 	}
 	else
@@ -111,6 +112,15 @@ static void menu_back_no_reset(void)
 	}
 }
 
+void menu_back_scroll(int scrollback)
+{
+	if (menu_depth > 0)
+	{
+		menu_depth--;
+		menu_goto(menu_stack[menu_depth].menu, menu_stack[menu_depth].position + scrollback, false, true);
+	}
+}
+
 void menu_back_if_clicked(void)
 {
 	if (lcd_clicked())
@@ -146,6 +156,16 @@ static void menu_submenu_no_reset(menu_func_t submenu)
 	}
 }
 
+void menu_submenu_scroll(menu_func_t submenu)
+{
+	if (menu_depth < MENU_DEPTH_MAX)
+	{
+		menu_stack[menu_depth].menu = menu_menu;
+		menu_stack[menu_depth++].position = lcd_encoder;
+		menu_goto(submenu, 0, false, false);
+	}
+}
+
 uint8_t menu_item_ret(void)
 {
 	lcd_beeper_quick_feedback();

+ 4 - 0
Firmware/menu.h

@@ -78,12 +78,16 @@ extern void menu_end(void);
 extern void menu_back(void);
 extern void menu_back(uint8_t nLevel);
 
+extern void menu_back_scroll(int scrollback);
+
 extern void menu_back_if_clicked(void);
 
 extern void menu_back_if_clicked_fb(void);
 
 extern void menu_submenu(menu_func_t submenu);
 
+extern void menu_submenu_scroll(menu_func_t submenu);
+
 extern uint8_t menu_item_ret(void);
 
 //extern int menu_draw_item_printf_P(char type_char, const char* format, ...);

+ 106 - 216
Firmware/ultralcd.cpp

@@ -52,16 +52,12 @@
 #include "config.h"
 
 
-int scrollstuff = 0;
-char longFilenameOLD[LONG_FILENAME_LENGTH];
-
-
 static void lcd_sd_updir();
 static void lcd_mesh_bed_leveling_settings();
 static void lcd_backlight_menu();
 
 int8_t ReInitLCD = 0;
-
+uint8_t scrollstuff = 0;
 
 int8_t SilentModeMenu = SILENT_MODE_OFF;
 uint8_t SilentModeMenu_MMU = 1; //activate mmu unit stealth mode
@@ -323,122 +319,84 @@ bool bSettings;                                   // flag (i.e. 'fake parameter'
 
 const char STR_SEPARATOR[] PROGMEM = "------------";
 
-
-static void lcd_implementation_drawmenu_sdfile_selected(uint8_t row, const char* filename, char* longFilename)
+typedef struct
 {
-    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_set_cursor(0, g);
-    lcd_print(' ');
-    }
-    lcd_set_cursor(0, row);
-    lcd_print('>');
-
-    if (longFilename[0] == '\0')
-    {
-        longFilename = filename;
-    }
-
-    int i = 1;
-    int j = 0;
-    char* longFilenameTMP = longFilename;
+	uint8_t offset = 0;
+	bool isDir = 0;
+	uint8_t row = 0;
+	const char* scrollPointer;
+    uint16_t fileCnt;
+} _menu_data_scroll_t;
+static_assert(sizeof(menu_data)>= sizeof(_menu_data_scroll_t),"_menu_data_scroll_t doesn't fit into menu_data");
 
-    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_set_cursor(i, row);
-        lcd_print(c);
-        i++;
-    }
-    n=n-i+1;
-    while(n--)
-        lcd_print(' ');
+static void lcd_filename_scroll() //this is a submenu
+{
+	_menu_data_scroll_t* _md = (_menu_data_scroll_t*)&(menu_data[0]);
+	if (menu_entering)
+	{
+		menu_entering = 0; //clear entering flag
+		lcd_scrollTimer.start();
+	}
+	bool rewindFlag = LCD_CLICKED || (lcd_encoder != 0); //go back to sd_menu.
+	if (rewindFlag == 1) _md->offset = 0;
+	if (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--)
+		{
+			char c = *(_md->scrollPointer + _md->offset +((LCD_WIDTH - ((_md->isDir)?2:1)) - i));
+			if (c == '\0')
+			{
+				lcd_scrollTimer.stop();
+				break; //stop at the end of the string
+			}
+			else
+			{
+				lcd_print(c);
+				lcd_scrollTimer.start();
+			}
+		}
+		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.
+	{
+		lcd_scrollTimer.start();
+		menu_back_scroll(lcd_encoder);
+	}
 }
-static void lcd_implementation_drawmenu_sdfile(uint8_t row, const char* filename, char* longFilename)
+static void lcd_implementation_drawmenu_sdfile(uint8_t row, const char* longFilename)
 {
     char c;
     uint8_t n = LCD_WIDTH - 1;
     lcd_set_cursor(0, row);
-    lcd_print(' ');
-    if (longFilename[0] != '\0')
-    {
-        filename = longFilename;
-        longFilename[LCD_WIDTH-1] = '\0';
-    }
-    while( ((c = *filename) != '\0') && (n>0) )
+	lcd_print((lcd_encoder == menu_item)?'>':' ');
+    while( ((c = *longFilename) != '\0') && (n>0) )
     {
         lcd_print(c);
-        filename++;
+        longFilename++;
         n--;
     }
     while(n--)
         lcd_print(' ');
 }
-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;
     uint8_t n = LCD_WIDTH - 2;
     lcd_set_cursor(0, row);
-    lcd_print('>');
-    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((lcd_encoder == menu_item)?'>':' ');
+	lcd_print(LCD_STR_FOLDER[0]);
+    while( ((c = *longFilename) != '\0') && (n>0) )
     {
         lcd_print(c);
-        filename++;
-        n--;
-    }
-    while(n--)
-        lcd_print(' ');
-}
-static void lcd_implementation_drawmenu_sddirectory(uint8_t row, const char* filename, char* longFilename)
-{
-    char c;
-    uint8_t n = LCD_WIDTH - 2;
-    lcd_set_cursor(0, row);
-    lcd_print(' ');
-    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++;
+        longFilename++;
         n--;
     }
     while(n--)
@@ -448,48 +406,26 @@ 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, str_fn, str_fnl) MENU_ITEM(sddirectory, str, str_fn, str_fnl)
-//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);
+#define MENU_ITEM_SDFILE(str_fn, str_fnl) do { if (menu_item_sdfile(str_fn, str_fnl)) return; } while (0)
 
 
 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 (lcd_draw_update)
-		{
-			lcd_set_cursor(0, menu_row);
-			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_draw_update || !lcd_scrollTimer.running())
 		{
-			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 (lcd_encoder == menu_item && !lcd_scrollTimer.running())
+			{
+				// lcd_beeper_quick_feedback();
+				_menu_data_scroll_t* _md = (_menu_data_scroll_t*)&(menu_data[0]);
+				_md->isDir = 1;
+				_md->row = menu_row;
+				_md->scrollPointer = (str_fnl[0] == '\0') ? str_fn : str_fnl;
+				menu_submenu_scroll(lcd_filename_scroll);
+				return 1; //stop menu generation early
+			}
+			else lcd_implementation_drawmenu_sddirectory(menu_row, (str_fnl[0] == '\0') ? str_fn : str_fnl);
 		}
 		if (menu_clicked && (lcd_encoder == menu_item))
 		{
@@ -497,80 +433,42 @@ uint8_t menu_item_sddir(const char* str_fn, char* str_fnl)
 			lcd_update_enabled = 0;
 			menu_action_sddirectory(str_fn);
 			lcd_update_enabled = 1;
-			return menu_item_ret();
+			/* return */ menu_item_ret();
+			return 1;
 		}
 	}
 	menu_item++;
 	return 0;
-
-#endif //NEW_SD_MENU
 }
 
-static uint8_t menu_item_sdfile(const char*
-#ifdef NEW_SD_MENU
-        str
-#endif //NEW_SD_MENU
-         ,const char* str_fn, char* str_fnl)
+static uint8_t menu_item_sdfile(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 (lcd_draw_update)
+		if (lcd_draw_update || !lcd_scrollTimer.running())
 		{
-//			printf_P(PSTR("menu file %d %d '%s'\n"), menu_row, menuData.sdcard_menu.viewState, str_fnl[0]?str_fnl:str_fn);
-			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*/
+			if (lcd_encoder == menu_item && !lcd_scrollTimer.running())
 			{
-				str_fnl[19] = 0;
-				lcd_printf_P(PSTR("%c%-19s"), (lcd_encoder == menu_item)?'>':' ', str_fnl[0]?str_fnl:str_fn);
+				// lcd_beeper_quick_feedback();
+				_menu_data_scroll_t* _md = (_menu_data_scroll_t*)&(menu_data[0]);
+				_md->isDir = 0;
+				_md->row = menu_row;
+				_md->scrollPointer = (str_fnl[0] == '\0') ? str_fn : str_fnl;
+				menu_submenu_scroll(lcd_filename_scroll);
+				return 1;
 			}
-
-//			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))
-		{
-			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_sdfile_selected(menu_row, str_fn, str_fnl);
-			else
-				lcd_implementation_drawmenu_sdfile(menu_row, str_fn, str_fnl);
+			else lcd_implementation_drawmenu_sdfile(menu_row, (str_fnl[0] == '\0') ? str_fn : str_fnl);
 		}
 		if (menu_clicked && (lcd_encoder == menu_item))
 		{
 		    lcd_consume_click();
 			menu_action_sdfile(str_fn);
-			return menu_item_ret();
+			/* return */ menu_item_ret();
+			return 1;
 		}
 	}
 	menu_item++;
 	return 0;
-#endif //NEW_SD_MENU
 }
 
 // Print temperature (nozzle/bed) (9 chars total)
@@ -740,16 +638,6 @@ void lcdui_print_time(void)
 //Print status line on status screen
 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
 		heating_status_counter++;
@@ -793,6 +681,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
+		const char* longFilenameOLD = (card.longFilename[0] ? card.longFilename : card.filename);
 		if(strlen(longFilenameOLD) > LCD_WIDTH)
 		{
 			int inters = 0;
@@ -4298,7 +4187,7 @@ static void prusa_stat_printinfo()
 	SERIAL_ECHO("][FEM:");
 	SERIAL_ECHO(itostr3(feedmultiply));
 	SERIAL_ECHO("][FNM:");
-	SERIAL_ECHO(longFilenameOLD);
+	SERIAL_ECHO(card.longFilename);
 	SERIAL_ECHO("][TIM:");
 	if (starttime != 0)
 	{
@@ -7390,12 +7279,18 @@ void lcd_sdcard_menu()
 	  presort_flag = false;
 	  card.presort();
   }
-  if (lcd_draw_update == 0 && LCD_CLICKED == 0)
-    //_delay(100);
+  if (!lcd_scrollTimer.running()) lcd_scrollTimer.start();
+  bool scrollEnter = lcd_scrollTimer.expired(500);
+  if (lcd_draw_update == 0 && LCD_CLICKED == 0 && !scrollEnter && !menu_entering)
     return; // nothing to do (so don't thrash the SD card)
-  uint16_t fileCnt = card.getnrfilenames();
-
-
+  _menu_data_scroll_t* _md = (_menu_data_scroll_t*)&(menu_data[0]);
+  if (menu_entering)
+  {
+    menu_entering = 0; //clear entering flag
+	lcd_draw_update = 1; //draw lines again
+    _md->fileCnt = card.getnrfilenames();
+  }
+  if (!scrollEnter) lcd_scrollTimer.start();
   MENU_BEGIN();
   MENU_ITEM_BACK_P(_T(bMain?MSG_MAIN:MSG_BACK));  // i.e. default menu-item / menu-item after card insertion
   card.getWorkDirName();
@@ -7408,28 +7303,21 @@ void lcd_sdcard_menu()
     MENU_ITEM_FUNCTION_P(PSTR(LCD_STR_FOLDER ".."), lcd_sd_updir);
   }
 
-  for (uint16_t i = 0; i < fileCnt; i++)
+  for (uint16_t i = 0; i < _md->fileCnt; i++)
   {
     if (menu_item == menu_line)
     {
-		const uint16_t nr = ((sdSort == SD_SORT_NONE) || farm_mode || (sdSort == SD_SORT_TIME)) ? (fileCnt - 1 - i) : i;
-		/*#ifdef SDCARD_RATHERRECENTFIRST
-			#ifndef SDCARD_SORT_ALPHA
-				fileCnt - 1 -
-			#endif
-		#endif
-		i;*/
+		const uint16_t nr = ((sdSort == SD_SORT_NONE) || farm_mode || (sdSort == SD_SORT_TIME)) ? (_md->fileCnt - 1 - i) : i;
 		#ifdef SDCARD_SORT_ALPHA
 			if (sdSort == SD_SORT_NONE) card.getfilename(nr);
 			else card.getfilename_sorted(nr);
 		#else
 			 card.getfilename(nr);
 		#endif
-			
 		if (card.filenameIsDir)
 			MENU_ITEM_SDDIR(card.filename, card.longFilename);
-		else
-			MENU_ITEM_SDFILE(_T(MSG_CARD_MENU), card.filename, card.longFilename);
+ 		else
+			MENU_ITEM_SDFILE(card.filename, card.longFilename);
     } else {
       MENU_ITEM_DUMMY();
     }
@@ -9041,6 +8929,8 @@ void menu_lcd_lcdupdate_func(void)
 		{
                if(menu_menu==lcd_sdcard_menu)
                     menu_back();
+               else if (menu_menu==lcd_filename_scroll)
+                    menu_back(2); //back 2 levels. Exit lcd_filename_scroll and lcd sd_card_menu
 			card.release();
 			LCD_MESSAGERPGM(_i("Card removed"));////MSG_SD_REMOVED
 		}

+ 2 - 0
Firmware/ultralcd.h

@@ -144,6 +144,8 @@ extern uint8_t SilentModeMenu_MMU;
 extern bool cancel_heatup;
 extern bool isPrintPaused;
 
+extern uint8_t scrollstuff;
+
 
 void lcd_ignore_click(bool b=true);
 void lcd_commands();