Commit a5ec7e53 authored by MagoKimbra's avatar MagoKimbra

Update V4.2.5

parent fc2d65a2
......@@ -114,7 +114,7 @@
* *
* Temperature sensor settings (4.7kohm PULLUP): *
* -2 is thermocouple with MAX6675 (only for sensor 0) *
* -1 is thermocouple with AD595 *
* -1 is thermocouple with AD595 or AD597 *
* 0 is not used *
* 1 is 100k thermistor - best choice for EPCOS 100k (4.7k pullup) *
* 2 is 200k thermistor - ATC Semitec 204GT-2 (4.7k pullup) *
......
......@@ -930,7 +930,8 @@ void ConfigSD_ResetDefault() {
void ConfigSD_StoreSettings() {
if(!IS_SD_INSERTED || card.isFileOpen() || card.sdprinting) return;
set_sd_dot();
card.startWrite((char *)CFG_SD_FILE);
card.setroot(true);
card.startWrite((char *)CFG_SD_FILE, false);
char buff[CFG_SD_MAX_VALUE_LEN];
#if HAS(POWER_CONSUMPTION_SENSOR)
ltoa(power_consumption_hour, buff, 10);
......@@ -940,7 +941,9 @@ void ConfigSD_ResetDefault() {
card.unparseKeyLine(cfgSD_KEY[SD_CFG_TME], buff);
ltoa(printer_usage_filament, buff, 10);
card.unparseKeyLine(cfgSD_KEY[SD_CFG_FIL], buff);
card.closeFile(false);
card.closeFile();
card.setlast();
config_last_update = millis();
unset_sd_dot();
}
......@@ -951,6 +954,7 @@ void ConfigSD_ResetDefault() {
char key[CFG_SD_MAX_KEY_LEN], value[CFG_SD_MAX_VALUE_LEN];
int k_idx;
int k_len, v_len;
card.setroot(true);
card.selectFile((char *)CFG_SD_FILE);
while(true) {
k_len = CFG_SD_MAX_KEY_LEN;
......@@ -979,7 +983,8 @@ void ConfigSD_ResetDefault() {
break;
}
}
card.closeFile(false);
card.closeFile();
card.setlast();
config_readed = true;
unset_sd_dot();
}
......
......@@ -78,11 +78,7 @@
* M29 - Stop SD write
* M30 - Delete file from SD (M30 filename.g)
* M31 - Output time since last M109 or SD card start to serial
* M32 - Select file and start SD print (Can be used _while_ printing from SD card files):
* syntax "M32 /path/filename#", or "M32 S<startpos bytes> !filename#"
* Call gcode file : "M32 P !filename#" and return to caller file after finishing (similar to #include).
* The '#' is necessary when calling from within sd files, as it stops buffer prereading
* M33 - Get the longname version of a path
* M32 - Make directory
* M42 - Change pin status via gcode Use M42 Px Sy to set pin x to value y, when omitting Px the onboard led will be used.
* M48 - Measure Z_Probe repeatability. M48 [P # of points] [X position] [Y position] [V_erboseness #] [E_ngage Probe] [L # of legs of travel]
* M70 - Power consumption sensor calibration
......
......@@ -32,6 +32,11 @@
#define analogInputToDigitalPin(p) ((p) + 0xA0)
#endif
#if DISABLED(CRITICAL_SECTION_START)
#define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli();
#define CRITICAL_SECTION_END SREG = _sreg;
#endif
//#define EXTERNALSERIAL // Force using arduino serial
#ifndef EXTERNALSERIAL
#include "HardwareSerial.h"
......@@ -161,6 +166,21 @@
}
while (!(SPSR & (1 << SPIF))) {}
}
static inline void digitalWrite(uint8_t pin,uint8_t value) {
::digitalWrite(pin,value);
}
static inline uint8_t digitalRead(uint8_t pin) {
return ::digitalRead(pin);
}
static inline void pinMode(uint8_t pin,uint8_t mode) {
::pinMode(pin,mode);
}
static inline unsigned long timeInMilliseconds() {
return millis();
}
protected:
private:
};
......
......@@ -2794,7 +2794,7 @@ void gcode_get_destination() {
printer_usage_filament += (destination[E_AXIS] - current_position[E_AXIS]);
#if ENABLED(NEXTION_GFX)
#if ENABLED(NEXTION) && ENABLED(NEXTION_GFX)
if((code_seen(axis_codes[X_AXIS]) || code_seen(axis_codes[Y_AXIS])) && code_seen(axis_codes[E_AXIS]))
gfx_line_to(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS]);
else
......@@ -3365,7 +3365,7 @@ inline void gcode_G28() {
#endif
}
#if ENABLED(NEXTION_GFX)
#if ENABLED(NEXTION) && ENABLED(NEXTION_GFX)
gfx_clear(X_MAX_POS, Y_MAX_POS, Z_MAX_POS);
gfx_cursor_to(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS]);
#endif
......@@ -4350,16 +4350,15 @@ inline void gcode_M17() {
*/
inline void gcode_M30() {
if (card.cardOK) {
card.fat.chdir();
card.closeFile();
card.deleteFile(current_command_args);
}
}
#endif
/**
/**
* M31: Get the time since the start of SD Print (or last M109)
*/
inline void gcode_M31() {
inline void gcode_M31() {
print_job_stop_ms = millis();
millis_t t = (print_job_stop_ms - print_job_start_ms) / 1000;
int min = t / 60, sec = t % 60;
......@@ -4368,18 +4367,18 @@ inline void gcode_M31() {
ECHO_LT(DB, time);
lcd_setstatus(time);
autotempShutdown();
}
}
/**
/**
* M32: Make Directory
*/
inline void gcode_M32() {
inline void gcode_M32() {
if (card.cardOK) {
card.fat.chdir();
card.makeDirectory(current_command_args);
card.mount();
}
}
}
#endif
/**
* M42: Change pin status via GCode
......@@ -7013,12 +7012,12 @@ void process_next_command() {
gcode_M29(); break;
case 30: // M30 <filename> Delete File
gcode_M30(); break;
case 31: // M31 take time since the start of the SD print or an M109 command
gcode_M31(); break;
case 32: // M32 - Make directory
gcode_M32(); break;
#endif //SDSUPPORT
case 31: // M31 take time since the start of the SD print or an M109 command
gcode_M31(); break;
case 42: // M42 -Change pin status via gcode
gcode_M42(); break;
......
......@@ -294,6 +294,16 @@
#define Z_MAX_ENDSTOP_INVERTING !Z_MAX_ENDSTOP_LOGIC
#define Z2_MAX_ENDSTOP_INVERTING !Z2_MAX_ENDSTOP_LOGIC
#define Z_PROBE_ENDSTOP_INVERTING !Z_PROBE_ENDSTOP_LOGIC
#undef ENDSTOPPULLUP_XMIN
#undef ENDSTOPPULLUP_YMIN
#undef ENDSTOPPULLUP_ZMIN
#undef ENDSTOPPULLUP_Z2MIN
#undef ENDSTOPPULLUP_XMAX
#undef ENDSTOPPULLUP_YMAX
#undef ENDSTOPPULLUP_ZMAX
#undef ENDSTOPPULLUP_Z2MAX
#undef ENDSTOPPULLUP_ZPROBE
#undef ENDSTOPPULLUP_EMIN
#else
#define X_MIN_ENDSTOP_INVERTING X_MIN_ENDSTOP_LOGIC
#define Y_MIN_ENDSTOP_INVERTING Y_MIN_ENDSTOP_LOGIC
......
......@@ -1532,23 +1532,31 @@ static void lcd_control_volumetric_menu() {
*/
void lcd_sdcard_menu() {
if (lcdDrawUpdate == 0 && LCD_CLICKED == 0) return; // nothing to do (so don't thrash the SD card)
card.updateSDFileCount();
uint16_t fileCnt = card.nrFiles;
char LongFileName[LONG_FILENAME_LENGTH + 1];
uint16_t fileCnt = card.getnrfilenames();
START_MENU(lcd_main_menu);
MENU_ITEM(back, MSG_MAIN, lcd_main_menu);
dir_t* p = NULL;
SdBaseFile *root = card.fat.vwd();
root->rewind();
while ((p = root->getLongFilename(p, tempLongFilename, 0, NULL)) != NULL) {
if (_menuItemNr == _lineNr) {
strcpy(LongFileName, tempLongFilename);
if (DIR_IS_SUBDIR(p)) {
MENU_ITEM(sddirectory, MSG_CARD_MENU, LongFileName);
card.getWorkDirName();
if (fullName[0] == '/') {
#if !PIN_EXISTS(SD_DETECT)
MENU_ITEM(function, LCD_STR_REFRESH MSG_REFRESH, lcd_sd_refresh);
#endif
}
else {
MENU_ITEM(sdfile, MSG_CARD_MENU, LongFileName);
MENU_ITEM(function, LCD_STR_FOLDER "..", lcd_sd_updir);
}
for (uint16_t i = 0; i < fileCnt; i++) {
if (_menuItemNr == _lineNr) {
card.getfilename(
#if ENABLED(SDCARD_RATHERRECENTFIRST)
fileCnt-1 -
#endif
i
);
if (card.filenameIsDir)
MENU_ITEM(sddirectory, MSG_CARD_MENU, fullName);
else
MENU_ITEM(sdfile, MSG_CARD_MENU, fullName);
}
else {
MENU_ITEM_DUMMY();
......
......@@ -10,7 +10,9 @@
#define SET_BIT(n,b,value) (n) ^= ((-value)^(n)) & (BIT(b))
// Macros for maths shortcuts
#define M_PI 3.1415926536
#ifndef M_PI
#define M_PI 3.1415926536
#endif
#define RADIANS(d) ((d)*M_PI/180.0)
#define DEGREES(r) ((r)*180.0/M_PI)
#define SIN_60 0.8660254037844386
......@@ -31,9 +33,4 @@
// Function macro
#define FORCE_INLINE __attribute__((always_inline)) inline
#if DISABLED(CRITICAL_SECTION_START)
#define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli();
#define CRITICAL_SECTION_END SREG = _sreg;
#endif
#endif //__MACROS_H
......@@ -212,24 +212,19 @@
}
#if ENABLED(SDSUPPORT)
void printrowsd(uint8_t row, const bool folder, const char* filename, char* longFilename) {
const char* cmd;
if (longFilename[0])
cmd = longFilename;
else
cmd = filename;
void printrowsd(uint8_t row, const bool folder, const char* filename) {
if (folder) {
folder_list[row]->setPic(18);
row_list[row]->attachPop(sdfolderPopCallback, row_list[row]);
} else if (cmd == "") {
} else if (filename == "") {
folder_list[row]->setPic(17);
row_list[row]->detachPop();
} else {
folder_list[row]->setPic(17);
row_list[row]->attachPop(sdfilePopCallback, row_list[row]);
}
row_list[row]->setText(cmd);
row_list[row]->setText(filename);
filename_list[row]->setText(filename);
}
......@@ -238,10 +233,10 @@
uint32_t i = 0;
card.getWorkDirName();
if (card.filename[0] != '/') {
if (fullName[0] != '/') {
Folderup.setPic(20);
Folderup.attachPop(sdfolderUpPopCallback);
sdfolder.setText(card.filename);
sdfolder.setText(fullName);
} else {
Folderup.detachPop();
Folderup.setPic(19);
......@@ -252,9 +247,9 @@
i = row + number;
if (i < fileCnt) {
card.getfilename(i);
printrowsd(row, card.filenameIsDir, card.filename, card.longFilename);
printrowsd(row, card.filenameIsDir, fullName);
} else {
printrowsd(row, false, "", (char*)"");
printrowsd(row, false, "");
}
}
sendCommand("ref 0");
......@@ -449,16 +444,15 @@
void PlayPausePopCallback(void *ptr) {
if (card.cardOK && card.isFileOpen()) {
if (card.sdprinting)
card.pauseSDPrint();
card.pausePrint();
else
card.startFileprint();
card.startPrint();
}
}
void StopPopCallback(void *ptr) {
quickStop();
card.sdprinting = false;
card.closeFile();
card.stopPrint();
autotempShutdown();
lcd_setstatus(MSG_PRINT_ABORTED, true);
}
......
......@@ -25,8 +25,21 @@
#include "Arduino.h"
#include "SDFat.h"
extern int8_t RFstricmp(const char* s1, const char* s2);
extern int8_t RFstrnicmp(const char* s1, const char* s2, size_t n);
extern int8_t RFstricmp(const char* s1, const char* s2) {
while(*s1 && (tolower(*s1) == tolower(*s2)))
s1++, s2++;
return (const uint8_t)tolower(*s1) - (const uint8_t)tolower(*s2);
}
extern int8_t RFstrnicmp(const char* s1, const char* s2, size_t n) {
while(n--) {
if(tolower(*s1) != tolower(*s2))
return (uint8_t)tolower(*s1) - (uint8_t)tolower(*s2);
s1++;
s2++;
}
return 0;
}
//------------------------------------------------------------------------------
static void pstrPrintln(PGM_P str) {
......@@ -310,6 +323,9 @@ bool SdFat::truncate(const char* path, uint32_t length) {
return file.truncate(length);
}
//==============================================================================
// SdBaseFile member functions
//------------------------------------------------------------------------------
// macro for debug
#define DBG_FAIL_MACRO // ECHO_ET(__LINE__)
//------------------------------------------------------------------------------
......@@ -1236,7 +1252,7 @@ bool SdBaseFile::open(SdBaseFile* dirFile, const uint8_t *dname, uint8_t oflag,
if (emptyFound)
p->name[0] = DIR_NAME_DELETED;
for(int8_t i=0;i< cVFATFoundCur - cVFATNeeded;i++) {
for(int8_t i = 0; i < cVFATFoundCur - cVFATNeeded; i++) {
if (dirFile->write(p, sizeof(dir_t)) < 0)
goto fail;
dirFile->sync();
......@@ -2876,7 +2892,7 @@ void (*SdBaseFile::oldDateTime_)(uint16_t& date, uint16_t& time) = 0; // NOLINT
//==============================================================================
// debug trace macro
#define SD_TRACE(m, b)
// #define SD_TRACE(m, b) Serial.print(m);Serial.println(b);
// SPI functions
#ifndef SOFTWARE_SPI
// functions for hardware SPI
......@@ -2885,7 +2901,6 @@ void (*SdBaseFile::oldDateTime_)(uint16_t& date, uint16_t& time) = 0; // NOLINT
#if (SPR0 != 0 || SPR1 != 1)
#error unexpected SPCR bits
#endif
//------------------------------------------------------------------------------
/**
* initialize SPI pins
......@@ -2910,7 +2925,7 @@ static uint8_t spiRec() {
/** SPI read data - only one call so force inline */
static inline __attribute__((always_inline))
uint8_t spiRec(uint8_t* buf, uint16_t nbyte) {
HAL::spiReadBlock(buf,nbyte);
HAL::spiReadBlock(buf, nbyte);
return 0;
}
//------------------------------------------------------------------------------
......@@ -2922,7 +2937,7 @@ static void spiSend(uint8_t b) {
/** SPI send block - only one call so force inline */
static inline __attribute__((always_inline))
void spiSendBlock(uint8_t token, const uint8_t* buf) {
HAL::spiSendBlock(token,buf);
HAL::spiSendBlock(token, buf);
}
static void spiSend(const uint8_t* buf, size_t n) {
HAL::spiSend(buf, n);
......@@ -3117,14 +3132,16 @@ uint32_t Sd2Card::cardSize() {
}
//------------------------------------------------------------------------------
void Sd2Card::chipSelectHigh() {
digitalWrite(chipSelectPin_, HIGH);
HAL::digitalWrite(chipSelectPin_, HIGH);
// insure MISO goes high impedance
HAL::spiSend(0XFF);
}
//------------------------------------------------------------------------------
void Sd2Card::chipSelectLow() {
#if DISABLED(SOFTWARE_SPI)
HAL::spiInit(spiRate_);
#ifndef SOFTWARE_SPI
spiInit(spiRate_);
#endif // SOFTWARE_SPI
digitalWrite(chipSelectPin_, LOW);
HAL::digitalWrite(chipSelectPin_, LOW);
}
//------------------------------------------------------------------------------
/** Erase a range of blocks.
......@@ -3199,25 +3216,25 @@ bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
errorCode_ = type_ = 0;
chipSelectPin_ = chipSelectPin;
// 16-bit init start time allows over a minute
uint16_t t0 = (uint16_t)millis();
uint16_t t0 = (uint16_t)HAL::timeInMilliseconds();
uint32_t arg;
pinMode(chipSelectPin_, OUTPUT);
digitalWrite(chipSelectPin_, HIGH);
HAL::pinMode(chipSelectPin_, OUTPUT);
HAL::digitalWrite(chipSelectPin_, HIGH);
spiBegin();
#ifndef SOFTWARE_SPI
#ifndef SOFTWARE_SPI
// set SCK rate for initialization commands
spiRate_ = SPI_SD_INIT_RATE;
spiInit(spiRate_);
#endif // SOFTWARE_SPI
#endif // SOFTWARE_SPI
// must supply min of 74 clock cycles with CS high.
for (uint8_t i = 0; i < 20; i++) spiSend(0XFF);
// command to go idle in SPI mode
while (cardCommand(CMD0, 0) != R1_IDLE_STATE) {
if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
if (((uint16_t)HAL::timeInMilliseconds() - t0) > SD_INIT_TIMEOUT) {
error(SD_CARD_ERROR_CMD0);
goto fail;
}
......@@ -3233,7 +3250,7 @@ bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
type(SD_CARD_TYPE_SD2);
break;
}
if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
if (((uint16_t)HAL::timeInMilliseconds() - t0) > SD_INIT_TIMEOUT) {
error(SD_CARD_ERROR_CMD8);
goto fail;
}
......@@ -3243,7 +3260,7 @@ bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
while (cardAcmd(ACMD41, arg) != R1_READY_STATE) {
// check for timeout
if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
if (((uint16_t)HAL::timeInMilliseconds() - t0) > SD_INIT_TIMEOUT) {
error(SD_CARD_ERROR_ACMD41);
goto fail;
}
......@@ -3258,19 +3275,19 @@ bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
// discard rest of ocr - contains allowed voltage range
for (uint8_t i = 0; i < 3; i++) spiRec();
}
#if USE_SD_CRC
#if USE_SD_CRC
if (cardCommand(CMD59, 1) > 1) {
error(SD_CARD_ERROR_CMD59);
goto fail;
}
#endif // USE_SD_CRC
#endif // USE_SD_CRC
chipSelectHigh();
#ifndef SOFTWARE_SPI
#ifndef SOFTWARE_SPI
return setSckRate(sckRateID);
#else // SOFTWARE_SPI
#else // SOFTWARE_SPI
return true;
#endif // SOFTWARE_SPI
#endif // SOFTWARE_SPI
fail:
chipSelectHigh();
......@@ -3315,9 +3332,9 @@ bool Sd2Card::readData(uint8_t* dst) {
bool Sd2Card::readData(uint8_t* dst, size_t count) {
uint16_t crc;
// wait for start block token
uint16_t t0 = millis();
uint16_t t0 = HAL::timeInMilliseconds();
while ((status_ = spiRec()) == 0XFF) {
if (((uint16_t)millis() - t0) > SD_READ_TIMEOUT) {
if (((uint16_t)HAL::timeInMilliseconds() - t0) > SD_READ_TIMEOUT) {
error(SD_CARD_ERROR_READ_TIMEOUT);
goto fail;
}
......@@ -3333,12 +3350,12 @@ bool Sd2Card::readData(uint8_t* dst, size_t count) {
}
// get crc
crc = (spiRec() << 8) | spiRec();
#if USE_SD_CRC
#if USE_SD_CRC
if (crc != CRC_CCITT(dst, count)) {
error(SD_CARD_ERROR_READ_CRC);
goto fail;
}
#endif // USE_SD_CRC
#endif // USE_SD_CRC
chipSelectHigh();
return true;
......@@ -3433,9 +3450,9 @@ bool Sd2Card::setSckRate(uint8_t sckRateID) {
//------------------------------------------------------------------------------
// wait for card to go not busy
bool Sd2Card::waitNotBusy(uint16_t timeoutMillis) {
uint16_t t0 = millis();
uint16_t t0 = HAL::timeInMilliseconds();
while (spiRec() != 0XFF) {
if (((uint16_t)millis() - t0) >= timeoutMillis) goto fail;
if (((uint16_t)HAL::timeInMilliseconds() - t0) >= timeoutMillis) goto fail;
}
return true;
......
......@@ -13,8 +13,11 @@ CardReader::CardReader() {
sdprinting = false;
cardOK = false;
saving = false;
workDirDepth = 0;
memset(workDirParents, 0, sizeof(workDirParents));
autostart_stilltocheck = true; //the SD start is delayed, because otherwise the serial cannot answer fast enough to make contact with the host software.
folderLevel = 0;
//power to SD reader
#if SDPOWER > -1
......@@ -24,8 +27,64 @@ CardReader::CardReader() {
next_autostart_ms = millis() + SPLASH_SCREEN_DURATION;
}
char* CardReader::createFilename(char* buffer, const dir_t& p) { //buffer > 12characters
char* pos = buffer, *src = (char*)p.name;
for (uint8_t i = 0; i < 11; i++, src++) {
if (*src == ' ') continue;
if (i == 8) *pos++ = '.';
*pos++ = *src;
}
*pos = 0;
return pos;
}
/**
* 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
*/
void CardReader::lsDive(SdBaseFile parent, const char* const match/*=NULL*/) {
dir_t* p;
uint8_t cnt = 0;
// Read the next entry from a directory
while ((p = parent.getLongFilename(p, fullName, 0, NULL)) != NULL) {
char pn0 = p->name[0];
if (pn0 == DIR_NAME_FREE) break;
if (pn0 == DIR_NAME_DELETED || pn0 == '.') continue;
if (fullName[0] == '.') continue;
if (!DIR_IS_FILE_OR_SUBDIR(p)) continue;
filenameIsDir = DIR_IS_SUBDIR(p);
if (!filenameIsDir && (p->name[8] != 'G' || p->name[9] == '~')) continue;
switch (lsAction) {
case LS_Count:
nrFiles++;
break;
case LS_GetFilename:
if (match != NULL) {
if (strcasecmp(match, fullName) == 0) return;
}
else if (cnt == nrFiles) return;
cnt++;
break;
}
} // while readDir
}
void CardReader::ls() {
root.openRoot(fat.vol());
root.ls(0, 0);
workDir = root;
curDir = &root;
}
void CardReader::initsd() {
cardOK = false;
if (root.isOpen()) root.close();
#if ENABLED(SDEXTRASLOW)
#define SPI_SPEED SPI_QUARTER_SPEED
......@@ -37,7 +96,7 @@ void CardReader::initsd() {
if(!fat.begin(SDSS, SPI_SPEED)
#if defined(LCD_SDSS) && (LCD_SDSS != SDSS)
&& !card.init(SPI_SPEED, LCD_SDSS)
&& !fat.begin(LCD_SDSS, SPI_SPEED)
#endif
) {
ECHO_LM(ER, SERIAL_SD_INIT_FAIL);
......@@ -46,8 +105,10 @@ void CardReader::initsd() {
cardOK = true;
ECHO_LM(DB, SERIAL_SD_CARD_OK);
}
fat.chdir();
fat.chdir(true);
root = *fat.vwd();
workDir = root;
curDir = &root;
}
void CardReader::mount() {
......@@ -57,7 +118,6 @@ void CardReader::mount() {
void CardReader::unmount() {
cardOK = false;
sdprinting = false;
folderLevel = 0;
}
void CardReader::startPrint() {
......@@ -70,7 +130,10 @@ void CardReader::pausePrint() {
void CardReader::continuePrint(bool intern) {}
void stopPrint() {}
void CardReader::stopPrint() {
sdprinting = false;
closeFile();
}
void CardReader::write_command(char* buf) {
char* begin = buf;
......@@ -92,15 +155,13 @@ void CardReader::write_command(char* buf) {
}
bool CardReader::selectFile(const char* filename, bool silent/*=false*/) {
SdBaseFile parent;
const char *oldP = filename;
if(!cardOK) return false;
file.close();
parent = *fat.vwd();
if (file.open(&parent, filename, O_READ)) {
if (file.open(curDir, filename, O_READ)) {
if ((oldP = strrchr(filename, '/')) != NULL)
oldP++;
else
......@@ -120,17 +181,6 @@ bool CardReader::selectFile(const char* filename, bool silent/*=false*/) {
}
}
char* CardReader::createFilename(char* buffer, const dir_t& p) { //buffer > 12characters
char* pos = buffer, *src = (char*)p.name;
for (uint8_t i = 0; i < 11; i++, src++) {
if (*src == ' ') continue;
if (i == 8) *pos++ = '.';
*pos++ = *src;
}
*pos = 0;
return pos;
}
void CardReader::printStatus() {
if (cardOK) {
ECHO_MV(SERIAL_SD_PRINTING_BYTE, sdpos);
......@@ -143,9 +193,8 @@ void CardReader::printStatus() {
void CardReader::startWrite(char *filename, bool lcd_status/*=true*/) {
if(!cardOK) return;
file.close();
fat.chdir();
if(!file.open(filename, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) {
if(!file.open(curDir, filename, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) {
ECHO_LMT(ER, SERIAL_SD_OPEN_FILE_FAIL, filename);
}
else {
......@@ -166,7 +215,7 @@ void CardReader::deleteFile(char *filename) {
if(fat.rmdir(filename))
ECHO_EMT(SERIAL_SD_FILE_DELETED, filename);
else
ECHO_EMT(SERIAL_SD_FILE_DELETION_ERR, filename);
ECHO_EM(SERIAL_SD_FILE_DELETION_ERR);
}
}
......@@ -190,15 +239,53 @@ void CardReader::makeDirectory(char *filename) {
}
}
void CardReader::ls() {
SdBaseFile file;
fat.chdir();
file.openRoot(fat.vol());
file.ls(0, 0);
updateSDFileCount();
/**
* Get the name of a file in the current directory by index
*/
void CardReader::getfilename(uint16_t nr, const char* const match/*=NULL*/) {
curDir = &workDir;
lsAction = LS_GetFilename;
nrFiles = nr;
curDir->rewind();
lsDive(*curDir, match);
}
void CardReader::closeFile(bool store_location) {
uint16_t CardReader::getnrfilenames() {
curDir = &workDir;
lsAction = LS_Count;
nrFiles = 0;
curDir->rewind();
lsDive(*curDir);
return nrFiles;
}
void CardReader::chdir(const char* relpath) {
SdBaseFile newfile;
SdBaseFile* parent = &root;
if (workDir.isOpen()) parent = &workDir;
if (!newfile.open(parent, relpath, O_READ)) {
ECHO_LMT(DB, SERIAL_SD_CANT_ENTER_SUBDIR, relpath);
}
else {
if (workDirDepth < SD_MAX_FOLDER_DEPTH) {
++workDirDepth;
for (int d = workDirDepth; d--;) workDirParents[d + 1] = workDirParents[d];
workDirParents[0] = *parent;
}
workDir = newfile;
}
}
void CardReader::updir() {
if (workDirDepth > 0) {
--workDirDepth;
workDir = workDirParents[0];
for (uint16_t d = 0; d < workDirDepth; d++)
workDirParents[d] = workDirParents[d + 1];
}
}
void CardReader::closeFile(bool store_location /*=false*/) {
file.sync();
file.close();
saving = false;
......@@ -220,7 +307,7 @@ void CardReader::checkautostart(bool force) {
if (!cardOK) return; // fail
}
fat.chdir();
fat.chdir(true);
if(selectFile("init.g", true)) startPrint();
}
......@@ -235,51 +322,15 @@ void CardReader::printingHasFinished() {
autotempShutdown();
}
void CardReader::updateSDFileCount() {
dir_t* p = NULL;
SdBaseFile *root = fat.vwd();
root->rewind();
nrFiles = 0;
while ((p = root->getLongFilename(p, NULL, 0, NULL))) {
if (! (DIR_IS_FILE(p) || DIR_IS_SUBDIR(p)))
continue;
if (folderLevel >= SD_MAX_FOLDER_DEPTH && DIR_IS_SUBDIR(p) && !(p->name[0]=='.' && p->name[1]=='.'))
continue;
nrFiles++;
if (nrFiles > 5000) // Arbitrary maximum, limited only by how long someone would scroll
return;
}
}
void CardReader::chdir(const char* name) {
bool changedir = false;
if (name[0]=='.' && name[1]=='.')
changedir = fat.chdir("/", true);
else
changedir = fat.chdir(name, true);
if (!changedir)
ECHO_LMT(DB, SERIAL_SD_CANT_ENTER_SUBDIR, name);
else
updateSDFileCount();
}
int8_t RFstricmp(const char* s1, const char* s2) {
while(*s1 && (tolower(*s1) == tolower(*s2)))
s1++, s2++;
return (const uint8_t)tolower(*s1) - (const uint8_t)tolower(*s2);
void CardReader::setroot(bool temporary /*=false*/) {
if(temporary) lastDir = workDir;
workDir = root;
curDir = &workDir;
}
int8_t RFstrnicmp(const char* s1, const char* s2, size_t n) {
while(n--) {
if(tolower(*s1) != tolower(*s2))
return (uint8_t)tolower(*s1) - (uint8_t)tolower(*s2);
s1++;
s2++;
}
return 0;
void CardReader::setlast() {
workDir = lastDir;
curDir = &workDir;
}
/**
......
......@@ -3,7 +3,7 @@
#if ENABLED(SDSUPPORT)
#define SD_MAX_FOLDER_DEPTH 5 // Maximum folder depth
#define SD_MAX_FOLDER_DEPTH 10 // Maximum folder depth
#define MAX_VFAT_ENTRIES (2)
#define FILENAME_LENGTH 13
/** Total size of the buffer used to store the long filenames */
......@@ -13,15 +13,13 @@
extern char tempLongFilename[LONG_FILENAME_LENGTH + 1];
extern char fullName[LONG_FILENAME_LENGTH * SD_MAX_FOLDER_DEPTH + SD_MAX_FOLDER_DEPTH + 1];
enum LsAction { LS_Count, LS_GetFilename };
#include "SdFat.h"
class CardReader {
public:
SdFat fat;
//Sd2Card card; // ~14 Byte
//SdVolume volume;
//SdFile root;
//SdFile dir[SD_MAX_FOLDER_DEPTH+1];
SdFile file;
CardReader();
......@@ -29,6 +27,7 @@ public:
void mount();
void unmount();
void ls();
void getfilename(uint16_t nr, const char* const match = NULL);
void startPrint();
void pausePrint();
void continuePrint(bool intern = false);
......@@ -43,8 +42,12 @@ public:
void closeFile(bool store_location = false);
char *createFilename(char *buffer, const dir_t &p);
void printingHasFinished();
void updateSDFileCount();
void chdir(const char* name);
void chdir(const char* relpath);
void updir();
void setroot(bool temporary = false);
void setlast();
uint16_t getnrfilenames();
void parseKeyLine(char* key, char* value, int &len_k, int &len_v);
void unparseKeyLine(const char* key, char* value);
......@@ -52,9 +55,9 @@ public:
FORCE_INLINE void setIndex(uint32_t newpos) { sdpos = newpos; file.seekSet(sdpos); }
FORCE_INLINE bool isFileOpen() { return file.isOpen(); }
FORCE_INLINE bool eof() { return sdpos >= filesize; }
FORCE_INLINE void updir() { chdir(".."); }
FORCE_INLINE int16_t get() { sdpos = file.curPosition(); return (int16_t)file.read(); }
FORCE_INLINE uint8_t percentDone() { return (isFileOpen() && filesize) ? sdpos / ((filesize + 99) / 100) : 0; }
FORCE_INLINE char* getWorkDirName() { workDir.getFilename(fullName); return fullName; }
//files init.g on the sd card are performed in a row
//this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset
......@@ -62,18 +65,17 @@ public:
public:
bool saving, sdprinting, cardOK, filenameIsDir;
uint16_t nrFiles; // counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory.
uint8_t folderLevel;
char cwd[SD_MAX_FOLDER_DEPTH*LONG_FILENAME_LENGTH+2];
private:
SdFile root, *curDir, workDir;
SdBaseFile root, *curDir, workDir, lastDir, workDirParents[SD_MAX_FOLDER_DEPTH];
Sd2Card card;
SdVolume volume;
uint16_t workDirDepth;
uint32_t filesize;
millis_t next_autostart_ms;
uint32_t sdpos;
uint16_t nrFiles; // counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory.
LsAction lsAction; //stored for recursion.
bool autostart_stilltocheck; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware.
void lsDive(SdBaseFile parent, const char* const match = NULL);
};
extern CardReader card;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment