Browse Source

Merge pull request #221 from daid/Marlin_v1

Long filename support for LCD display
pull/1/head
ErikZalm 12 years ago
parent
commit
b86336c3f5
  1. 2
      Marlin/Marlin.pde
  2. 2
      Marlin/Sd2Card.cpp
  3. 38
      Marlin/SdBaseFile.cpp
  4. 4
      Marlin/SdBaseFile.h
  5. 7
      Marlin/SdFatConfig.h
  6. 48
      Marlin/SdFatStructs.h
  7. 8
      Marlin/cardreader.cpp
  8. 3
      Marlin/cardreader.h
  9. 16
      Marlin/ultralcd.pde

2
Marlin/Marlin.pde

@ -1822,5 +1822,3 @@ void setPwmFrequency(uint8_t pin, int val)
} }
} }
#endif #endif

2
Marlin/Sd2Card.cpp

@ -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

38
Marlin/SdBaseFile.cpp

@ -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,11 +1108,17 @@ 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));
if (n != sizeof(dir_t)) return n == 0 ? 0 : -1; 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; 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;
} }

4
Marlin/SdBaseFile.h

@ -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.

7
Marlin/SdFatConfig.h

@ -108,6 +108,13 @@ 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

48
Marlin/SdFatStructs.h

@ -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" */

8
Marlin/cardreader.cpp

@ -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(" ");

3
Marlin/cardreader.h

@ -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:

16
Marlin/ultralcd.pde

@ -2310,8 +2310,16 @@ 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");
if (card.longFilename[0])
{
card.longFilename[LCD_WIDTH-1] = '\0';
lcd.print(card.longFilename);
}
else
{
lcd.print(card.filename); lcd.print(card.filename);
} }
}
if((activeline==line) && CLICKED) if((activeline==line) && CLICKED)
{ {
BLOCK BLOCK
@ -2335,10 +2343,18 @@ void MainMenu::showSD()
enquecommand("M24"); enquecommand("M24");
beep(); beep();
status=Main_Status; status=Main_Status;
if (card.longFilename[0])
{
card.longFilename[LCD_WIDTH-1] = '\0';
lcd_status(card.longFilename);
}
else
{
lcd_status(card.filename); lcd_status(card.filename);
} }
} }
} }
}
} }
break; break;

Loading…
Cancel
Save