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 | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -369,7 +369,6 @@ bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) { | ||||
|  * | ||||
|  * \param[in] blockNumber Logical block to be read. | ||||
|  * \param[out] dst Pointer to the location that will receive the data. | ||||
|  | ||||
|  * \return The value one, true, is returned for success and | ||||
|  * the value zero, false, is returned for failure. | ||||
|  */ | ||||
| @@ -639,5 +638,4 @@ bool Sd2Card::writeStop() { | ||||
|   return false; | ||||
| } | ||||
|  | ||||
|  | ||||
| #endif | ||||
| @@ -867,7 +867,7 @@ bool SdBaseFile::openParent(SdBaseFile* dir) { | ||||
|   } | ||||
|   // search for parent in '../..' | ||||
|   do { | ||||
|     if (file.readDir(&entry) != 32) goto fail; | ||||
|     if (file.readDir(&entry, NULL) != 32) goto fail; | ||||
|     c = entry.firstClusterLow; | ||||
|     c |= (uint32_t)entry.firstClusterHigh << 16; | ||||
|   } while (c != cluster); | ||||
| @@ -1108,11 +1108,17 @@ int16_t SdBaseFile::read(void* buf, uint16_t nbyte) { | ||||
|  * readDir() called before a directory has been opened, this is not | ||||
|  * 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; | ||||
|   // if not a directory file or miss-positioned return an error | ||||
|   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) { | ||||
|     n = read(dir, sizeof(dir_t)); | ||||
|     if (n != sizeof(dir_t)) return n == 0 ? 0 : -1; | ||||
| @@ -1120,6 +1126,34 @@ int8_t SdBaseFile::readDir(dir_t* dir) { | ||||
|     if (dir->name[0] == DIR_NAME_FREE) return 0; | ||||
|     // skip empty entries and entry for .  and .. | ||||
|     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 | ||||
|     if (DIR_IS_FILE_OR_SUBDIR(dir)) return n; | ||||
|   } | ||||
|   | ||||
| @@ -283,7 +283,7 @@ class SdBaseFile { | ||||
|   bool printName(); | ||||
|   int16_t read(); | ||||
|   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); | ||||
|   bool remove(); | ||||
|   /** 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. | ||||
|    * \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: | ||||
|    * static uint8_t remove(SdBaseFile* dirFile, const char* path); | ||||
|    * \param[in] dirFile The directory that contains the file. | ||||
|   | ||||
| @@ -108,6 +108,13 @@ uint8_t const SOFT_SPI_SCK_PIN = 13; | ||||
|  * a pure virtual function is called. | ||||
|  */ | ||||
| #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 | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -22,6 +22,8 @@ | ||||
|  | ||||
| #ifndef SdFatStructs_h | ||||
| #define SdFatStructs_h | ||||
|  | ||||
| #define PACKED __attribute__((__packed__)) | ||||
| /** | ||||
|  * \file | ||||
|  * \brief FAT file structures | ||||
| @@ -95,7 +97,7 @@ struct partitionTable { | ||||
|   uint32_t firstSector; | ||||
|            /** Length of the partition, in blocks. */ | ||||
|   uint32_t totalSectors; | ||||
| }; | ||||
| } PACKED; | ||||
| /** Type name for partitionTable */ | ||||
| typedef struct partitionTable part_t; | ||||
| //------------------------------------------------------------------------------ | ||||
| @@ -119,7 +121,7 @@ struct masterBootRecord { | ||||
|   uint8_t  mbrSig0; | ||||
|            /** Second MBR signature byte. Must be 0XAA */ | ||||
|   uint8_t  mbrSig1; | ||||
| }; | ||||
| } PACKED; | ||||
| /** Type name for masterBootRecord */ | ||||
| typedef struct masterBootRecord mbr_t; | ||||
| //------------------------------------------------------------------------------ | ||||
| @@ -247,7 +249,7 @@ struct fat_boot { | ||||
|   uint8_t  bootSectorSig0; | ||||
|            /** must be 0XAA */ | ||||
|   uint8_t  bootSectorSig1; | ||||
| }; | ||||
| } PACKED; | ||||
| /** Type name for FAT Boot Sector */ | ||||
| typedef struct fat_boot fat_boot_t; | ||||
| //------------------------------------------------------------------------------ | ||||
| @@ -401,7 +403,7 @@ struct fat32_boot { | ||||
|   uint8_t  bootSectorSig0; | ||||
|            /** must be 0XAA */ | ||||
|   uint8_t  bootSectorSig1; | ||||
| }; | ||||
| } PACKED; | ||||
| /** Type name for FAT32 Boot Sector */ | ||||
| typedef struct fat32_boot fat32_boot_t; | ||||
| //------------------------------------------------------------------------------ | ||||
| @@ -441,7 +443,7 @@ struct fat32_fsinfo { | ||||
|   uint8_t  reserved2[12]; | ||||
|            /** must be 0X00, 0X00, 0X55, 0XAA */ | ||||
|   uint8_t  tailSignature[4]; | ||||
| }; | ||||
| } PACKED; | ||||
| /** Type name for FAT32 FSINFO Sector */ | ||||
| typedef struct fat32_fsinfo fat32_fsinfo_t; | ||||
| //------------------------------------------------------------------------------ | ||||
| @@ -539,12 +541,46 @@ struct directoryEntry { | ||||
|   uint16_t firstClusterLow; | ||||
|            /** 32-bit unsigned holding this file's size in bytes. */ | ||||
|   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 | ||||
| // | ||||
| /** Type name for directoryEntry */ | ||||
| typedef struct directoryEntry dir_t; | ||||
| /** Type name for directoryVFATEntry */ | ||||
| typedef struct directoryVFATEntry vfat_t; | ||||
| /** escape for name[0] = 0XE5 */ | ||||
| uint8_t const DIR_NAME_0XE5 = 0X05; | ||||
| /** name[0] value for entry that is free after being "deleted" */ | ||||
|   | ||||
| @@ -51,7 +51,7 @@ void  CardReader::lsDive(const char *prepend,SdFile parent) | ||||
|   dir_t p; | ||||
|  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 | ||||
|     { | ||||
| @@ -429,16 +429,16 @@ void CardReader::checkautostart(bool force) | ||||
|    | ||||
|   char autoname[30]; | ||||
|   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]); | ||||
|   dir_t p; | ||||
|  | ||||
|   root.rewind(); | ||||
|    | ||||
|   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]); | ||||
|     //Serial.print((char*)p.name); | ||||
|     //Serial.print(" "); | ||||
|   | ||||
| @@ -45,7 +45,8 @@ public: | ||||
|   bool saving; | ||||
|   bool sdprinting ;   | ||||
|   bool cardOK ; | ||||
|   char filename[12]; | ||||
|   char filename[13]; | ||||
|   char longFilename[LONG_FILENAME_LENGTH]; | ||||
|   bool filenameIsDir; | ||||
|   int lastnr; //last number of the autostart; | ||||
| private: | ||||
|   | ||||
| @@ -2310,8 +2310,16 @@ void MainMenu::showSD() | ||||
|           //Serial.print("Filenr:");Serial.println(i-2); | ||||
|           lcd.setCursor(0,line);lcdprintPGM(" "); | ||||
|           if(card.filenameIsDir) lcd.print("\005"); | ||||
|           if (card.longFilename[0]) | ||||
|           { | ||||
|             card.longFilename[LCD_WIDTH-1] = '\0'; | ||||
|             lcd.print(card.longFilename); | ||||
|           } | ||||
|           else | ||||
|           { | ||||
|             lcd.print(card.filename); | ||||
|           } | ||||
|         } | ||||
|         if((activeline==line) && CLICKED) | ||||
|         { | ||||
|           BLOCK | ||||
| @@ -2335,10 +2343,18 @@ void MainMenu::showSD() | ||||
|             enquecommand("M24"); | ||||
|             beep();  | ||||
|             status=Main_Status; | ||||
|             if (card.longFilename[0]) | ||||
|             { | ||||
|               card.longFilename[LCD_WIDTH-1] = '\0'; | ||||
|               lcd_status(card.longFilename); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|               lcd_status(card.filename); | ||||
|             } | ||||
|           } | ||||
|         }  | ||||
|       } | ||||
|        | ||||
|     } | ||||
|       break; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user