From 76da81c1dec742e5267645721ceb2c7b36a7e943 Mon Sep 17 00:00:00 2001
From: Bob-the-Kuhn <bob.kuhn@att.net>
Date: Sun, 30 Jul 2017 00:02:41 -0500
Subject: [PATCH] minimize SD card reads when using SDCARD_SORT_ALPHA (Re-ARM
 board)

Because of the Re-ARM card's pinout there is only one SPI connected to
the RepRap Discount Full Graphic LCD display.  The LCD responds to ANY
SCK transitions no matter if it's enable is inactive.  The result is
garbage (usually bars) on the LCD display whenever there is SD card
activity.

This code minimizes this by only accessing the SD card when changing
directory levels if :
SDCARD_SORT_ALPHA is enabled
SDSORT_USES_RAM is true
SDSORT_CACHE_NAMES is true

The code changes result in file names being pulled from the ALPHA SORT
memory array rather than the SD card.

The code also gives the file count and file index functions their own
variables.  When they shared a common variable the index function
sometimes resulted in the file count being short by 1.

=======================================================================

cardreader.cpp & pins_RAMPS_RE_ARM.h changes

Added another condition to cardreader.cpp to enable getting file names
only from RAM.

pins_RAMPS_RE_ARM.h :
Added comments about the SD card accesses and the LCD display
Combined all versions into this one.
---
 Marlin/cardreader.cpp      | 18 ++++++++++++----
 Marlin/cardreader.h        |  2 ++
 Marlin/pins_RAMPS_RE_ARM.h | 16 +++++++--------
 Marlin/ultralcd.cpp        | 42 ++++++++++++++++++++------------------
 4 files changed, 46 insertions(+), 32 deletions(-)

diff --git a/Marlin/cardreader.cpp b/Marlin/cardreader.cpp
index d862c6c42f..bd4bb317ca 100644
--- a/Marlin/cardreader.cpp
+++ b/Marlin/cardreader.cpp
@@ -74,9 +74,12 @@ char *createFilename(char *buffer, const dir_t &p) { //buffer > 12characters
 /**
  * Dive into a folder and recurse depth-first to perform a pre-set operation lsAction:
  *   LS_Count       - Add +1 to nrFiles for every file within the parent
- *   LS_GetFilename - Get the filename of the file indexed by nrFiles
+ *   LS_GetFilename - Get the filename of the file indexed by nrFile_index
  *   LS_SerialPrint - Print the full path and size of each file to serial output
  */
+ 
+uint16_t nrFile_index;
+
 void CardReader::lsDive(const char *prepend, SdFile parent, const char * const match/*=NULL*/) {
   dir_t p;
   uint8_t cnt = 0;
@@ -130,7 +133,7 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
 
       if (!filenameIsDir && (p.name[8] != 'G' || p.name[9] == '~')) continue;
 
-      switch (lsAction) {
+      switch (lsAction) {  // 1 based file count
         case LS_Count:
           nrFiles++;
           break;
@@ -148,7 +151,7 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
           if (match != NULL) {
             if (strcasecmp(match, filename) == 0) return;
           }
-          else if (cnt == nrFiles) return;
+          else if (cnt == nrFile_index) return;  // 0 based index
           cnt++;
           break;
       }
@@ -596,7 +599,7 @@ void CardReader::getfilename(uint16_t nr, const char * const match/*=NULL*/) {
   #endif // SDSORT_CACHE_NAMES
   curDir = &workDir;
   lsAction = LS_GetFilename;
-  nrFiles = nr;
+  nrFile_index = nr;
   curDir->rewind();
   lsDive("", *curDir, match);
 }
@@ -861,6 +864,13 @@ void CardReader::updir() {
 
 #endif // SDCARD_SORT_ALPHA
 
+#if (ENABLED(SDCARD_SORT_ALPHA) && SDSORT_USES_RAM && SDSORT_CACHE_NAMES)  
+ // if true - don't need to access the SD card for file names
+  uint16_t CardReader::get_num_Files() {return nrFiles;}
+#else
+  uint16_t CardReader::get_num_Files() {return getnrfilenames(); } 
+#endif
+
 void CardReader::printingHasFinished() {
   stepper.synchronize();
   file.close();
diff --git a/Marlin/cardreader.h b/Marlin/cardreader.h
index c9bea6036b..657e9f379c 100644
--- a/Marlin/cardreader.h
+++ b/Marlin/cardreader.h
@@ -69,6 +69,8 @@ public:
   void updir();
   void setroot();
 
+  uint16_t get_num_Files();
+  
   #if ENABLED(SDCARD_SORT_ALPHA)
     void presort();
     void getfilename_sorted(const uint16_t nr);
diff --git a/Marlin/pins_RAMPS_RE_ARM.h b/Marlin/pins_RAMPS_RE_ARM.h
index 9afa514c0a..6dda906c62 100644
--- a/Marlin/pins_RAMPS_RE_ARM.h
+++ b/Marlin/pins_RAMPS_RE_ARM.h
@@ -52,7 +52,7 @@
 //
 // Servos
 //
-#define SERVO0_PIN         11  
+#define SERVO0_PIN         11
 #define SERVO1_PIN          6  // also on J5-1
 #define SERVO2_PIN          5
 #define SERVO3_PIN          4  // 5V output - PWM capable
@@ -214,9 +214,9 @@
  *
  * All controllers can use J3 and J5 on the Re-ARM board.  Custom cabling will be required.
  */
- 
-/** 
- * Smart LCD adapter 
+
+/**
+ * Smart LCD adapter
  *
  * The Smart LCD adapter can be used for the two 10 pin LCD controllers such as
  * REPRAP_DISCOUNT_SMART_CONTROLLER.  It can't be used for controllers that use
@@ -224,7 +224,7 @@
  * is needed to pick up 5V for the EXP1 connection.
  *
  * SD card on the LCD uses the same SPI signals as the LCD. This results in garbage/lines
- * on the LCD display during accesses of the SD card. The menus/code has been arranged so 
+ * on the LCD display during accesses of the SD card. The menus/code has been arranged so
  * that the garbage/lines are erased immediately after the SD card accesses are completed.
  */
 
@@ -248,7 +248,7 @@
   #if ENABLED(REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER) && ENABLED(SDSUPPORT)
     #define SDCARD_SORT_ALPHA           // Using SORT feature to keep one directory level in RAM
                                         // When going up/down directory levels the SD card is
-                                        // accessed but the garbage/lines are removed when the 
+                                        // accessed but the garbage/lines are removed when the
                                         // LCD updates
 
     // SD Card Sorting options
@@ -262,7 +262,7 @@
       #define SDSORT_DYNAMIC_RAM false  // Use dynamic allocation (within SD menus). Least expensive option. Set SDSORT_LIMIT before use!
     #endif
   #endif
-  
+
   #define BTN_EN1             31  // J3-2 & AUX-4
   #define BTN_EN2             33  // J3-4 & AUX-4
   #define BTN_ENC             35  // J3-3 & AUX-4
@@ -286,7 +286,7 @@
   //#define MOSI                51  // system defined J3-10 & AUX-3
   //#define SCK                 52  // system defined J3-9 & AUX-3
   //#define SS_PIN              53  // system defined J3-5 & AUX-3 - sometimes called SDSS
- 
+
 
   #if ENABLED(VIKI2) || ENABLED(miniVIKI)
     #define LCD_SCREEN_ROT_180
diff --git a/Marlin/ultralcd.cpp b/Marlin/ultralcd.cpp
index 57c3e3227d..3afd278fd4 100644
--- a/Marlin/ultralcd.cpp
+++ b/Marlin/ultralcd.cpp
@@ -3507,7 +3507,7 @@ void kill_screen(const char* lcd_msg) {
     void lcd_sdcard_menu() {
       ENCODER_DIRECTION_MENUS();
       if (!lcdDrawUpdate && !lcd_clicked) return; // nothing to do (so don't thrash the SD card)
-      const uint16_t fileCnt = card.getnrfilenames();
+      const uint16_t fileCnt = card.get_num_Files();
       START_MENU();
       MENU_BACK(MSG_MAIN);
       card.getWorkDirName();
@@ -3520,27 +3520,29 @@ void kill_screen(const char* lcd_msg) {
         MENU_ITEM(function, LCD_STR_FOLDER "..", lcd_sd_updir);
       }
 
-      for (uint16_t i = 0; i < fileCnt; i++) {
-        if (_menuLineNr == _thisItemNr) {
-          const uint16_t nr =
-            #if ENABLED(SDCARD_RATHERRECENTFIRST) && DISABLED(SDCARD_SORT_ALPHA)
-              fileCnt - 1 -
+      if (fileCnt) {
+        for (uint16_t i = 0; i < fileCnt; i++) {
+          if (_menuLineNr == _thisItemNr) {
+            const uint16_t nr =
+              #if ENABLED(SDCARD_RATHERRECENTFIRST) && DISABLED(SDCARD_SORT_ALPHA)
+                fileCnt - 1 -
+              #endif
+            i;
+
+            #if ENABLED(SDCARD_SORT_ALPHA)
+              card.getfilename_sorted(nr);
+            #else
+              card.getfilename(nr);
             #endif
-          i;
 
-          #if ENABLED(SDCARD_SORT_ALPHA)
-            card.getfilename_sorted(nr);
-          #else
-            card.getfilename(nr);
-          #endif
-
-          if (card.filenameIsDir)
-            MENU_ITEM(sddirectory, MSG_CARD_MENU, card.filename, card.longFilename);
-          else
-            MENU_ITEM(sdfile, MSG_CARD_MENU, card.filename, card.longFilename);
-        }
-        else {
-          MENU_ITEM_DUMMY();
+            if (card.filenameIsDir)
+              MENU_ITEM(sddirectory, MSG_CARD_MENU, card.filename, card.longFilename);
+            else
+              MENU_ITEM(sdfile, MSG_CARD_MENU, card.filename, card.longFilename);
+          }
+          else {
+            MENU_ITEM_DUMMY();
+          }
         }
       }
       END_MENU();