Merge pull request #221 from daid/Marlin_v1
Long filename support for LCD display
This commit is contained in:
		| @@ -1822,5 +1822,3 @@ void setPwmFrequency(uint8_t pin, int val) | |||||||
|   } |   } | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -369,7 +369,6 @@ bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) { | |||||||
|  * |  * | ||||||
|  * \param[in] blockNumber Logical block to be read. |  * \param[in] blockNumber Logical block to be read. | ||||||
|  * \param[out] dst Pointer to the location that will receive the data. |  * \param[out] dst Pointer to the location that will receive the data. | ||||||
|  |  | ||||||
|  * \return The value one, true, is returned for success and |  * \return The value one, true, is returned for success and | ||||||
|  * the value zero, false, is returned for failure. |  * the value zero, false, is returned for failure. | ||||||
|  */ |  */ | ||||||
| @@ -639,5 +638,4 @@ bool Sd2Card::writeStop() { | |||||||
|   return false; |   return false; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | #endif | ||||||
| #endif |  | ||||||
|   | |||||||
| @@ -867,7 +867,7 @@ bool SdBaseFile::openParent(SdBaseFile* dir) { | |||||||
|   } |   } | ||||||
|   // search for parent in '../..' |   // search for parent in '../..' | ||||||
|   do { |   do { | ||||||
|     if (file.readDir(&entry) != 32) goto fail; |     if (file.readDir(&entry, NULL) != 32) goto fail; | ||||||
|     c = entry.firstClusterLow; |     c = entry.firstClusterLow; | ||||||
|     c |= (uint32_t)entry.firstClusterHigh << 16; |     c |= (uint32_t)entry.firstClusterHigh << 16; | ||||||
|   } while (c != cluster); |   } while (c != cluster); | ||||||
| @@ -1108,10 +1108,16 @@ int16_t SdBaseFile::read(void* buf, uint16_t nbyte) { | |||||||
|  * readDir() called before a directory has been opened, this is not |  * readDir() called before a directory has been opened, this is not | ||||||
|  * a directory file or an I/O error occurred. |  * a directory file or an I/O error occurred. | ||||||
|  */ |  */ | ||||||
| int8_t SdBaseFile::readDir(dir_t* dir) { | int8_t SdBaseFile::readDir(dir_t* dir, char* longFilename) { | ||||||
|   int16_t n; |   int16_t n; | ||||||
|   // if not a directory file or miss-positioned return an error |   // if not a directory file or miss-positioned return an error | ||||||
|   if (!isDir() || (0X1F & curPosition_)) return -1; |   if (!isDir() || (0X1F & curPosition_)) return -1; | ||||||
|  |    | ||||||
|  |   //If we have a longFilename buffer, mark it as invalid. If we find a long filename it will be filled automaticly. | ||||||
|  |   if (longFilename != NULL) | ||||||
|  |   { | ||||||
|  |   	longFilename[0] = '\0'; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   while (1) { |   while (1) { | ||||||
|     n = read(dir, sizeof(dir_t)); |     n = read(dir, sizeof(dir_t)); | ||||||
| @@ -1120,6 +1126,34 @@ int8_t SdBaseFile::readDir(dir_t* dir) { | |||||||
|     if (dir->name[0] == DIR_NAME_FREE) return 0; |     if (dir->name[0] == DIR_NAME_FREE) return 0; | ||||||
|     // skip empty entries and entry for .  and .. |     // skip empty entries and entry for .  and .. | ||||||
|     if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') continue; |     if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') continue; | ||||||
|  |     //Fill the long filename if we have a long filename entry, | ||||||
|  | 	// long filename entries are stored before the actual filename. | ||||||
|  | 	if (DIR_IS_LONG_NAME(dir) && longFilename != NULL) | ||||||
|  |     { | ||||||
|  |     	vfat_t *VFAT = (vfat_t*)dir; | ||||||
|  | 		//Sanity check the VFAT entry. The first cluster is always set to zero. And th esequence number should be higher then 0 | ||||||
|  |     	if (VFAT->firstClusterLow == 0 && (VFAT->sequenceNumber & 0x1F) > 0 && (VFAT->sequenceNumber & 0x1F) <= MAX_VFAT_ENTRIES) | ||||||
|  |     	{ | ||||||
|  | 			//TODO: Store the filename checksum to verify if a none-long filename aware system modified the file table. | ||||||
|  |     		n = ((VFAT->sequenceNumber & 0x1F) - 1) * 13; | ||||||
|  | 			longFilename[n+0] = VFAT->name1[0]; | ||||||
|  | 			longFilename[n+1] = VFAT->name1[1]; | ||||||
|  | 			longFilename[n+2] = VFAT->name1[2]; | ||||||
|  | 			longFilename[n+3] = VFAT->name1[3]; | ||||||
|  | 			longFilename[n+4] = VFAT->name1[4]; | ||||||
|  | 			longFilename[n+5] = VFAT->name2[0]; | ||||||
|  | 			longFilename[n+6] = VFAT->name2[1]; | ||||||
|  | 			longFilename[n+7] = VFAT->name2[2]; | ||||||
|  | 			longFilename[n+8] = VFAT->name2[3]; | ||||||
|  | 			longFilename[n+9] = VFAT->name2[4]; | ||||||
|  | 			longFilename[n+10] = VFAT->name2[5]; | ||||||
|  | 			longFilename[n+11] = VFAT->name3[0]; | ||||||
|  | 			longFilename[n+12] = VFAT->name3[1]; | ||||||
|  | 			//If this VFAT entry is the last one, add a NUL terminator at the end of the string | ||||||
|  | 			if (VFAT->sequenceNumber & 0x40) | ||||||
|  | 				longFilename[n+13] = '\0'; | ||||||
|  | 		} | ||||||
|  |     } | ||||||
|     // return if normal file or subdirectory |     // return if normal file or subdirectory | ||||||
|     if (DIR_IS_FILE_OR_SUBDIR(dir)) return n; |     if (DIR_IS_FILE_OR_SUBDIR(dir)) return n; | ||||||
|   } |   } | ||||||
| @@ -1788,4 +1822,4 @@ void (*SdBaseFile::oldDateTime_)(uint16_t& date, uint16_t& time) = 0;  // NOLINT | |||||||
| #endif  // ALLOW_DEPRECATED_FUNCTIONS | #endif  // ALLOW_DEPRECATED_FUNCTIONS | ||||||
|  |  | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -283,7 +283,7 @@ class SdBaseFile { | |||||||
|   bool printName(); |   bool printName(); | ||||||
|   int16_t read(); |   int16_t read(); | ||||||
|   int16_t read(void* buf, uint16_t nbyte); |   int16_t read(void* buf, uint16_t nbyte); | ||||||
|   int8_t readDir(dir_t* dir); |   int8_t readDir(dir_t* dir, char* longFilename); | ||||||
|   static bool remove(SdBaseFile* dirFile, const char* path); |   static bool remove(SdBaseFile* dirFile, const char* path); | ||||||
|   bool remove(); |   bool remove(); | ||||||
|   /** Set the file's current position to zero. */ |   /** Set the file's current position to zero. */ | ||||||
| @@ -455,7 +455,7 @@ class SdBaseFile { | |||||||
|    * \param[out] dir The dir_t struct that will receive the data. |    * \param[out] dir The dir_t struct that will receive the data. | ||||||
|    * \return bytes read for success zero for eof or -1 for failure. |    * \return bytes read for success zero for eof or -1 for failure. | ||||||
|    */ |    */ | ||||||
|   int8_t readDir(dir_t& dir) {return readDir(&dir);}  // NOLINT |   int8_t readDir(dir_t& dir, char* longFilename) {return readDir(&dir, longFilename);}  // NOLINT | ||||||
|   /** \deprecated Use: |   /** \deprecated Use: | ||||||
|    * static uint8_t remove(SdBaseFile* dirFile, const char* path); |    * static uint8_t remove(SdBaseFile* dirFile, const char* path); | ||||||
|    * \param[in] dirFile The directory that contains the file. |    * \param[in] dirFile The directory that contains the file. | ||||||
| @@ -480,4 +480,4 @@ class SdBaseFile { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif  // SdBaseFile_h | #endif  // SdBaseFile_h | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -108,7 +108,14 @@ uint8_t const SOFT_SPI_SCK_PIN = 13; | |||||||
|  * a pure virtual function is called. |  * a pure virtual function is called. | ||||||
|  */ |  */ | ||||||
| #define USE_CXA_PURE_VIRTUAL 1 | #define USE_CXA_PURE_VIRTUAL 1 | ||||||
|  | /** | ||||||
|  |  * Defines for long (vfat) filenames | ||||||
|  |  */ | ||||||
|  | /** Number of VFAT entries used. Every entry has 13 UTF-16 characters */ | ||||||
|  | #define MAX_VFAT_ENTRIES (2) | ||||||
|  | /** Total size of the buffer used to store the long filenames */ | ||||||
|  | #define LONG_FILENAME_LENGTH (13*MAX_VFAT_ENTRIES+1) | ||||||
| #endif  // SdFatConfig_h | #endif  // SdFatConfig_h | ||||||
|  |  | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -22,6 +22,8 @@ | |||||||
|  |  | ||||||
| #ifndef SdFatStructs_h | #ifndef SdFatStructs_h | ||||||
| #define SdFatStructs_h | #define SdFatStructs_h | ||||||
|  |  | ||||||
|  | #define PACKED __attribute__((__packed__)) | ||||||
| /** | /** | ||||||
|  * \file |  * \file | ||||||
|  * \brief FAT file structures |  * \brief FAT file structures | ||||||
| @@ -95,7 +97,7 @@ struct partitionTable { | |||||||
|   uint32_t firstSector; |   uint32_t firstSector; | ||||||
|            /** Length of the partition, in blocks. */ |            /** Length of the partition, in blocks. */ | ||||||
|   uint32_t totalSectors; |   uint32_t totalSectors; | ||||||
| }; | } PACKED; | ||||||
| /** Type name for partitionTable */ | /** Type name for partitionTable */ | ||||||
| typedef struct partitionTable part_t; | typedef struct partitionTable part_t; | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| @@ -119,7 +121,7 @@ struct masterBootRecord { | |||||||
|   uint8_t  mbrSig0; |   uint8_t  mbrSig0; | ||||||
|            /** Second MBR signature byte. Must be 0XAA */ |            /** Second MBR signature byte. Must be 0XAA */ | ||||||
|   uint8_t  mbrSig1; |   uint8_t  mbrSig1; | ||||||
| }; | } PACKED; | ||||||
| /** Type name for masterBootRecord */ | /** Type name for masterBootRecord */ | ||||||
| typedef struct masterBootRecord mbr_t; | typedef struct masterBootRecord mbr_t; | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| @@ -247,7 +249,7 @@ struct fat_boot { | |||||||
|   uint8_t  bootSectorSig0; |   uint8_t  bootSectorSig0; | ||||||
|            /** must be 0XAA */ |            /** must be 0XAA */ | ||||||
|   uint8_t  bootSectorSig1; |   uint8_t  bootSectorSig1; | ||||||
| }; | } PACKED; | ||||||
| /** Type name for FAT Boot Sector */ | /** Type name for FAT Boot Sector */ | ||||||
| typedef struct fat_boot fat_boot_t; | typedef struct fat_boot fat_boot_t; | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| @@ -401,7 +403,7 @@ struct fat32_boot { | |||||||
|   uint8_t  bootSectorSig0; |   uint8_t  bootSectorSig0; | ||||||
|            /** must be 0XAA */ |            /** must be 0XAA */ | ||||||
|   uint8_t  bootSectorSig1; |   uint8_t  bootSectorSig1; | ||||||
| }; | } PACKED; | ||||||
| /** Type name for FAT32 Boot Sector */ | /** Type name for FAT32 Boot Sector */ | ||||||
| typedef struct fat32_boot fat32_boot_t; | typedef struct fat32_boot fat32_boot_t; | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| @@ -441,7 +443,7 @@ struct fat32_fsinfo { | |||||||
|   uint8_t  reserved2[12]; |   uint8_t  reserved2[12]; | ||||||
|            /** must be 0X00, 0X00, 0X55, 0XAA */ |            /** must be 0X00, 0X00, 0X55, 0XAA */ | ||||||
|   uint8_t  tailSignature[4]; |   uint8_t  tailSignature[4]; | ||||||
| }; | } PACKED; | ||||||
| /** Type name for FAT32 FSINFO Sector */ | /** Type name for FAT32 FSINFO Sector */ | ||||||
| typedef struct fat32_fsinfo fat32_fsinfo_t; | typedef struct fat32_fsinfo fat32_fsinfo_t; | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| @@ -539,12 +541,46 @@ struct directoryEntry { | |||||||
|   uint16_t firstClusterLow; |   uint16_t firstClusterLow; | ||||||
|            /** 32-bit unsigned holding this file's size in bytes. */ |            /** 32-bit unsigned holding this file's size in bytes. */ | ||||||
|   uint32_t fileSize; |   uint32_t fileSize; | ||||||
| }; | } PACKED; | ||||||
|  | /** | ||||||
|  |  * \struct directoryVFATEntry | ||||||
|  |  * \brief VFAT long filename directory entry | ||||||
|  |  * | ||||||
|  |  * directoryVFATEntries are found in the same list as normal directoryEntry. | ||||||
|  |  * But have the attribute field set to DIR_ATT_LONG_NAME. | ||||||
|  |  *  | ||||||
|  |  * Long filenames are saved in multiple directoryVFATEntries. | ||||||
|  |  * Each entry containing 13 UTF-16 characters. | ||||||
|  |  */ | ||||||
|  | struct directoryVFATEntry { | ||||||
|  |   /** | ||||||
|  |    * Sequence number. Consists of 2 parts: | ||||||
|  |    *  bit 6:   indicates first long filename block for the next file | ||||||
|  |    *  bit 0-4: the position of this long filename block (first block is 1) | ||||||
|  |    */ | ||||||
|  |   uint8_t  sequenceNumber; | ||||||
|  |   /** First set of UTF-16 characters */ | ||||||
|  |   uint16_t name1[5];//UTF-16 | ||||||
|  |   /** attributes (at the same location as in directoryEntry), always 0x0F */ | ||||||
|  |   uint8_t  attributes; | ||||||
|  |   /** Reserved for use by Windows NT. Always 0. */ | ||||||
|  |   uint8_t  reservedNT; | ||||||
|  |   /** Checksum of the short 8.3 filename, can be used to checked if the file system as modified by a not-long-filename aware implementation. */ | ||||||
|  |   uint8_t  checksum; | ||||||
|  |   /** Second set of UTF-16 characters */ | ||||||
|  |   uint16_t name2[6];//UTF-16 | ||||||
|  |   /** firstClusterLow is always zero for longFilenames */ | ||||||
|  |   uint16_t firstClusterLow; | ||||||
|  |   /** Third set of UTF-16 characters */ | ||||||
|  |   uint16_t name3[2];//UTF-16 | ||||||
|  | } PACKED; | ||||||
| //------------------------------------------------------------------------------ | //------------------------------------------------------------------------------ | ||||||
| // Definitions for directory entries | // Definitions for directory entries | ||||||
| // | // | ||||||
| /** Type name for directoryEntry */ | /** Type name for directoryEntry */ | ||||||
| typedef struct directoryEntry dir_t; | typedef struct directoryEntry dir_t; | ||||||
|  | /** Type name for directoryVFATEntry */ | ||||||
|  | typedef struct directoryVFATEntry vfat_t; | ||||||
| /** escape for name[0] = 0XE5 */ | /** escape for name[0] = 0XE5 */ | ||||||
| uint8_t const DIR_NAME_0XE5 = 0X05; | uint8_t const DIR_NAME_0XE5 = 0X05; | ||||||
| /** name[0] value for entry that is free after being "deleted" */ | /** name[0] value for entry that is free after being "deleted" */ | ||||||
| @@ -607,4 +643,4 @@ static inline uint8_t DIR_IS_FILE_OR_SUBDIR(const dir_t* dir) { | |||||||
| #endif  // SdFatStructs_h | #endif  // SdFatStructs_h | ||||||
|  |  | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -51,7 +51,7 @@ void  CardReader::lsDive(const char *prepend,SdFile parent) | |||||||
|   dir_t p; |   dir_t p; | ||||||
|  uint8_t cnt=0; |  uint8_t cnt=0; | ||||||
|   |   | ||||||
|   while (parent.readDir(p) > 0) |   while (parent.readDir(p, longFilename) > 0) | ||||||
|   { |   { | ||||||
|     if( DIR_IS_SUBDIR(&p) && lsAction!=LS_Count && lsAction!=LS_GetFilename) // hence LS_SerialPrint |     if( DIR_IS_SUBDIR(&p) && lsAction!=LS_Count && lsAction!=LS_GetFilename) // hence LS_SerialPrint | ||||||
|     { |     { | ||||||
| @@ -429,16 +429,16 @@ void CardReader::checkautostart(bool force) | |||||||
|    |    | ||||||
|   char autoname[30]; |   char autoname[30]; | ||||||
|   sprintf(autoname,"auto%i.g",lastnr); |   sprintf(autoname,"auto%i.g",lastnr); | ||||||
|   for(int8_t i=0;i<(int)strlen(autoname);i++) |   for(int8_t i=0;i<(int8_t)strlen(autoname);i++) | ||||||
|     autoname[i]=tolower(autoname[i]); |     autoname[i]=tolower(autoname[i]); | ||||||
|   dir_t p; |   dir_t p; | ||||||
|  |  | ||||||
|   root.rewind(); |   root.rewind(); | ||||||
|    |    | ||||||
|   bool found=false; |   bool found=false; | ||||||
|   while (root.readDir(p) > 0)  |   while (root.readDir(p, NULL) > 0)  | ||||||
|   { |   { | ||||||
|     for(int8_t i=0;i<(int)strlen((char*)p.name);i++) |     for(int8_t i=0;i<(int8_t)strlen((char*)p.name);i++) | ||||||
|     p.name[i]=tolower(p.name[i]); |     p.name[i]=tolower(p.name[i]); | ||||||
|     //Serial.print((char*)p.name); |     //Serial.print((char*)p.name); | ||||||
|     //Serial.print(" "); |     //Serial.print(" "); | ||||||
|   | |||||||
| @@ -45,7 +45,8 @@ public: | |||||||
|   bool saving; |   bool saving; | ||||||
|   bool sdprinting ;   |   bool sdprinting ;   | ||||||
|   bool cardOK ; |   bool cardOK ; | ||||||
|   char filename[12]; |   char filename[13]; | ||||||
|  |   char longFilename[LONG_FILENAME_LENGTH]; | ||||||
|   bool filenameIsDir; |   bool filenameIsDir; | ||||||
|   int lastnr; //last number of the autostart; |   int lastnr; //last number of the autostart; | ||||||
| private: | private: | ||||||
| @@ -72,4 +73,4 @@ private: | |||||||
| #define IS_SD_PRINTING (false) | #define IS_SD_PRINTING (false) | ||||||
|  |  | ||||||
| #endif //SDSUPPORT | #endif //SDSUPPORT | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -2310,7 +2310,15 @@ void MainMenu::showSD() | |||||||
|           //Serial.print("Filenr:");Serial.println(i-2); |           //Serial.print("Filenr:");Serial.println(i-2); | ||||||
|           lcd.setCursor(0,line);lcdprintPGM(" "); |           lcd.setCursor(0,line);lcdprintPGM(" "); | ||||||
|           if(card.filenameIsDir) lcd.print("\005"); |           if(card.filenameIsDir) lcd.print("\005"); | ||||||
|           lcd.print(card.filename); |           if (card.longFilename[0]) | ||||||
|  |           { | ||||||
|  |             card.longFilename[LCD_WIDTH-1] = '\0'; | ||||||
|  |             lcd.print(card.longFilename); | ||||||
|  |           } | ||||||
|  |           else | ||||||
|  |           { | ||||||
|  |             lcd.print(card.filename); | ||||||
|  |           } | ||||||
|         } |         } | ||||||
|         if((activeline==line) && CLICKED) |         if((activeline==line) && CLICKED) | ||||||
|         { |         { | ||||||
| @@ -2335,7 +2343,15 @@ void MainMenu::showSD() | |||||||
|             enquecommand("M24"); |             enquecommand("M24"); | ||||||
|             beep();  |             beep();  | ||||||
|             status=Main_Status; |             status=Main_Status; | ||||||
|             lcd_status(card.filename); |             if (card.longFilename[0]) | ||||||
|  |             { | ||||||
|  |               card.longFilename[LCD_WIDTH-1] = '\0'; | ||||||
|  |               lcd_status(card.longFilename); | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |               lcd_status(card.filename); | ||||||
|  |             } | ||||||
|           } |           } | ||||||
|         }  |         }  | ||||||
|       } |       } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user