diff --git a/Configuration.h b/Configuration.h index 331c3e5..d274ac4 100644 --- a/Configuration.h +++ b/Configuration.h @@ -24,8 +24,8 @@ Licence: GPL #define CONFIGURATION_H #define NAME "RepRapFirmware" -#define VERSION "1.00h-dc42" -#define DATE "2015-02-11" +#define VERSION "1.00i-dc42" +#define DATE "2015-02-16" #define AUTHORS "reprappro, dc42, zpl" #define FLASH_SAVE_ENABLED (1) diff --git a/DDA.cpp b/DDA.cpp index 55d1f61..9bfbfad 100644 --- a/DDA.cpp +++ b/DDA.cpp @@ -19,8 +19,8 @@ int32_t DDA::GetTimeLeft() const //pre(state == executing || state == frozen || state == completed) { return (state == completed) ? 0 - : (state == executing) ? (int32_t)(moveStartTime + timeNeeded - Platform::GetInterruptClocks()) - : (int32_t)timeNeeded; + : (state == executing) ? (int32_t)(moveStartTime + clocksNeeded - Platform::GetInterruptClocks()) + : (int32_t)clocksNeeded; } void DDA::DebugPrintVector(const char *name, const float *vec, size_t len) const @@ -551,14 +551,14 @@ void DDA::Prepare() params.decelStartDistance = totalDistance - decelDistance; // Convert the accelerate/decelerate distances to times - float accelStopTime = (topSpeed - startSpeed)/acceleration; - float decelStartTime = accelStopTime + (params.decelStartDistance - accelDistance)/topSpeed; - float totalTime = decelStartTime + (topSpeed - endSpeed)/acceleration; - timeNeeded = (uint32_t)(totalTime * stepClockRate); + const float accelStopTime = (topSpeed - startSpeed)/acceleration; + const float decelStartTime = accelStopTime + (params.decelStartDistance - accelDistance)/topSpeed; + const float totalTime = decelStartTime + (topSpeed - endSpeed)/acceleration; + clocksNeeded = (uint32_t)(totalTime * stepClockRate); params.startSpeedTimesCdivA = (uint32_t)((startSpeed * stepClockRate)/acceleration); params.topSpeedTimesCdivA = (uint32_t)((topSpeed * stepClockRate)/acceleration); - params.decelStartClocks = decelStartTime * stepClockRate; + params.decelStartClocks = (uint32_t)(decelStartTime * stepClockRate); params.topSpeedTimesCdivAPlusDecelStartClocks = params.topSpeedTimesCdivA + params.decelStartClocks; params.accelClocksMinusAccelDistanceTimesCdivTopSpeed = (uint32_t)((accelStopTime - (accelDistance/topSpeed)) * stepClockRate); params.compFactor = 1.0 - startSpeed/topSpeed; diff --git a/DDA.h b/DDA.h index f6f1ad8..763b3e2 100644 --- a/DDA.h +++ b/DDA.h @@ -116,7 +116,7 @@ private: float targetNextSpeed; // The speed that the next move would like to start at // These are calculated from the above and used in the ISR, so they are set up by Prepare() - uint32_t timeNeeded; // in clocks + uint32_t clocksNeeded; // in clocks uint32_t moveStartTime; // clock count at which the move was started uint32_t firstStepTime; // in clocks, relative to the start of the move diff --git a/GCodes.cpp b/GCodes.cpp index 1b9bda2..802a2d7 100644 --- a/GCodes.cpp +++ b/GCodes.cpp @@ -28,10 +28,8 @@ const char GCodes::axisLetters[AXES] = {'X', 'Y', 'Z'}; GCodes::GCodes(Platform* p, Webserver* w) + : active(false), platform(p), webserver(w), stackPointer(0) { - active = false; - platform = p; - webserver = w; webGCode = new GCodeBuffer(platform, "web: "); fileGCode = new GCodeBuffer(platform, "file: "); serialGCode = new GCodeBuffer(platform, "serial: "); @@ -81,7 +79,6 @@ void GCodes::Reset() fileBeingWritten = NULL; endStopsToCheck = 0; doingFileMacro = false; - fractionOfFilePrinted = -1.0; dwellWaiting = false; stackPointer = 0; state = GCodeState::normal; @@ -103,6 +100,19 @@ void GCodes::Reset() filePos = moveFilePos = noFilePosition; } +float GCodes::FractionOfFilePrinted() const +{ + if (isPaused) + { + return (fileToPrint.IsLive()) ? fileToPrint.FractionRead() : -1.0; + } + if (stackPointer == 0) + { + return (fileBeingPrinted.IsLive() && !doingFileMacro) ? fileBeingPrinted.FractionRead() : -1.0; + } + return (stack[0].fileState.IsLive() && !stack[0].doingFileMacro) ? stack[0].fileState.FractionRead() : -1.0; +} + void GCodes::DoFilePrint(GCodeBuffer* gb, StringRef& reply) { for (int i = 0; i < 50 && fileBeingPrinted.IsLive(); ++i) @@ -306,7 +316,6 @@ void GCodes::Spin() fileBeingPrinted.MoveFrom(fileToPrint); moveBuffer[DRIVES] = pausedMoveBuffer[DRIVES]; reprap.GetMove()->SetFeedrate(pausedMoveBuffer[DRIVES]); - fractionOfFilePrinted = -1.0; fileGCode->Resume(); HandleReply(false, gbCurrent, reply.Pointer(), 'M', 24, false); isPaused = false; @@ -505,10 +514,6 @@ void GCodes::Push() stack[stackPointer].drivesRelative = drivesRelative; stack[stackPointer].axesRelative = axesRelative; stack[stackPointer].doingFileMacro = doingFileMacro; - if (stackPointer == 0) - { - fractionOfFilePrinted = fileBeingPrinted.FractionRead(); // save this so that we don't return the fraction of the macro file read - } stackPointer++; platform->PushMessageIndent(); } @@ -523,10 +528,6 @@ void GCodes::Pop() } stackPointer--; - if (stackPointer == 0) - { - fractionOfFilePrinted = -1.0; // restore live updates of fraction read from the file being printed - } state = stack[stackPointer].state; gbCurrent = stack[stackPointer].gb; moveBuffer[DRIVES] = stack[stackPointer].feedrate; @@ -2274,7 +2275,6 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply) else { fileBeingPrinted.MoveFrom(fileToPrint); - fractionOfFilePrinted = -1.0; } break; @@ -2315,7 +2315,6 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply) } } pausedFanValue = platform->GetFanValue(); - fractionOfFilePrinted = fileBeingPrinted.FractionRead(); fileToPrint.MoveFrom(fileBeingPrinted); fileGCode->Pause(); state = GCodeState::pausing1; @@ -3741,12 +3740,12 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply) } else if (!seen) { - reply.printf("Axis currents (mA) - X:%.1f, Y:%.1f, Z:%.1f, E:", - platform->MotorCurrent(X_AXIS), platform->MotorCurrent(Y_AXIS), - platform->MotorCurrent(Z_AXIS)); + reply.printf("Axis currents (mA) - X:%d, Y:%d, Z:%d, E:", + (int)platform->MotorCurrent(X_AXIS), (int)platform->MotorCurrent(Y_AXIS), + (int)platform->MotorCurrent(Z_AXIS)); for(int8_t drive = AXES; drive < DRIVES; drive++) { - reply.catf("%.1f%c", platform->MotorCurrent(drive), (drive < DRIVES - 1) ? ':' : '\n'); + reply.catf("%d%c", (int)platform->MotorCurrent(drive), (drive < DRIVES - 1) ? ':' : '\n'); } } } diff --git a/GCodes.h b/GCodes.h index d0fdd85..d5b52f2 100644 --- a/GCodes.h +++ b/GCodes.h @@ -192,7 +192,6 @@ class GCodes uint16_t toBeHomed; // Bitmap of axes still to be homed bool doingFileMacro; // Are we executing a macro file? int oldToolNumber, newToolNumber; // Tools being changed - float fractionOfFilePrinted; // Only used to record the main file when a macro is being printed const char* eofString; // What's at the end of an HTML file? uint8_t eofStringCounter; // Check the... uint8_t eofStringLength; // ... EoF string as we read. @@ -219,21 +218,6 @@ class GCodes //***************************************************************************************************** -inline float GCodes::FractionOfFilePrinted() const -{ - if (fractionOfFilePrinted < 0.0) - { - return fileBeingPrinted.FractionRead(); - } - - if (!fileBeingPrinted.IsLive()) - { - return -1.0; - } - - return fractionOfFilePrinted; -} - inline bool GCodes::PrintingAFile() const { return FractionOfFilePrinted() >= 0.0; diff --git a/Move.cpp b/Move.cpp index 25d2ba6..3bd7ef0 100644 --- a/Move.cpp +++ b/Move.cpp @@ -199,26 +199,47 @@ void Move::Spin() // See if we can add another move to the ring if (!addNoMoreMoves && ddaRingAddPointer->GetState() == DDA::empty) { + DDA *dda = ddaRingAddPointer; if (reprap.Debug(moduleMove)) { - ddaRingAddPointer->PrintIfHasStepError(); + dda->PrintIfHasStepError(); } - // If there's a G Code move available, add it to the DDA ring for processing. - float nextMove[DRIVES + 1]; - EndstopChecks endStopsToCheck; - bool noDeltaMapping; - FilePosition filePos; - if (reprap.GetGCodes()->ReadMove(nextMove, endStopsToCheck, noDeltaMapping, filePos)) + + // In order to react faster to speed and extrusion rate changes, only add more moves if the total duration of + // all un-frozen moves is less than 2 seconds, or the total duration of all but the first un-frozen move is + // less than 0.5 seconds. + float unPreparedTime = 0.0; + float prevMoveTime = 0.0; + for(;;) { - currentFeedrate = nextMove[DRIVES]; // might be G1 with just an F field - if (!noDeltaMapping || !IsDeltaMode()) + dda = dda->GetPrevious(); + if (dda->GetState() != DDA::provisional) { - Transform(nextMove); + break; } - if (ddaRingAddPointer->Init(nextMove, endStopsToCheck, IsDeltaMode() && !noDeltaMapping, filePos)) + unPreparedTime += prevMoveTime; + prevMoveTime = dda->CalcTime(); + } + + if (unPreparedTime < 0.5 || unPreparedTime + prevMoveTime < 2.0) + { + // If there's a G Code move available, add it to the DDA ring for processing. + float nextMove[DRIVES + 1]; + EndstopChecks endStopsToCheck; + bool noDeltaMapping; + FilePosition filePos; + if (reprap.GetGCodes()->ReadMove(nextMove, endStopsToCheck, noDeltaMapping, filePos)) { - ddaRingAddPointer = ddaRingAddPointer->GetNext(); - idleCount = 0; + currentFeedrate = nextMove[DRIVES]; // might be G1 with just an F field + if (!noDeltaMapping || !IsDeltaMode()) + { + Transform(nextMove); + } + if (ddaRingAddPointer->Init(nextMove, endStopsToCheck, IsDeltaMode() && !noDeltaMapping, filePos)) + { + ddaRingAddPointer = ddaRingAddPointer->GetNext(); + idleCount = 0; + } } } } diff --git a/Platform.cpp b/Platform.cpp index 14ff79d..0b49e0a 100644 --- a/Platform.cpp +++ b/Platform.cpp @@ -1251,7 +1251,7 @@ void Platform::Disable(size_t drive) void Platform::SetMotorCurrent(byte drive, float current) { - unsigned short pot = (unsigned short)(0.256*current*8.0*senseResistor/maxStepperDigipotVoltage); + unsigned short pot = (unsigned short)((0.256*current*8.0*senseResistor + maxStepperDigipotVoltage/2)/maxStepperDigipotVoltage); // Message(HOST_MESSAGE, "Set pot to: "); // snprintf(scratchString, STRING_LENGTH, "%d", pot); // Message(HOST_MESSAGE, scratchString); @@ -1880,7 +1880,7 @@ bool FileStore::Open(const char* directory, const char* fileName, bool write) ? platform->GetMassStorage()->CombineName(directory, fileName) : fileName; writing = write; - lastBufferEntry = FILE_BUF_LEN - 1; + lastBufferEntry = FILE_BUF_LEN; FRESULT openReturn = f_open(&file, location, (writing) ? FA_CREATE_ALWAYS | FA_WRITE : FA_OPEN_EXISTING | FA_READ); if (openReturn != FR_OK) @@ -1944,45 +1944,32 @@ bool FileStore::Seek(FilePosition pos) if (writing) { WriteBuffer(); - FRESULT fr = f_lseek(&file, pos); - if (fr == FR_OK) - { - bufferPointer = 0; - lastBufferEntry = 0; - return true; - } } - else - { - // Keep file reads aligned on a 256-byte boundary - FRESULT fr = f_lseek(&file, pos & ~(FilePosition)(FILE_BUF_LEN - 1)); - if (fr == FR_OK) - { - bool ok = ReadBuffer(); - if (ok) - { - bufferPointer = pos & (FilePosition)(FILE_BUF_LEN - 1); - return true; - } - } - } - return false; + FRESULT fr = f_lseek(&file, pos); + bufferPointer = (writing) ? 0 : FILE_BUF_LEN; + return fr == FR_OK; } FilePosition FileStore::GetPosition() const { FilePosition pos = file.fptr; - if (!writing && bufferPointer < lastBufferEntry) + if (writing) + { + pos += bufferPointer; + } + else if (bufferPointer < lastBufferEntry) { pos -= (lastBufferEntry - bufferPointer); } return pos; } +#if 0 // not currently used bool FileStore::GoToEnd() { return Seek(Length()); } +#endif FilePosition FileStore::Length() const { @@ -1996,7 +1983,7 @@ FilePosition FileStore::Length() const float FileStore::FractionRead() const { - uint32_t len = Length(); + FilePosition len = Length(); if (len == 0) { return 0.0; diff --git a/Platform.h b/Platform.h index 8c01476..3e8d1ed 100644 --- a/Platform.h +++ b/Platform.h @@ -75,8 +75,13 @@ Licence: GPL // DRIVES +#if 0 // swap X with E0 +#define STEP_PINS {X2, 25, 5, 14, 41, 39, X4, 49} +#define DIRECTION_PINS {X3, 26, 4, 15, 35, 53, 51, 48} +#else #define STEP_PINS {14, 25, 5, X2, 41, 39, X4, 49} #define DIRECTION_PINS {15, 26, 4, X3, 35, 53, 51, 48} +#endif #define FORWARDS true // What to send to go... #define BACKWARDS (!FORWARDS) // ...in each direction #define DIRECTIONS {BACKWARDS, FORWARDS, FORWARDS, FORWARDS, FORWARDS, FORWARDS, FORWARDS, FORWARDS} // What each axis needs to make it go forwards - defaults @@ -373,7 +378,9 @@ public: bool Close(); // Shut the file and tidy up bool Seek(FilePosition pos); // Jump to pos in the file FilePosition GetPosition() const; // Return the current position in the file, assuming we are reading the file +#if 0 // not currently used bool GoToEnd(); // Position the file at the end (so you can write on the end). +#endif FilePosition Length() const; // File size in bytes float FractionRead() const; // How far in we are void Duplicate(); // Create a second reference to this file @@ -900,12 +907,12 @@ public: return f->Flush(); } - uint32_t GetPosition() const + FilePosition GetPosition() const { return f->GetPosition(); } - bool Seek(uint32_t position) + bool Seek(FilePosition position) { return f->Seek(position); } @@ -915,7 +922,7 @@ public: return (f == NULL ? -1.0 : f->FractionRead()); } - uint32_t Length() const + FilePosition Length() const { return f->Length(); } diff --git a/Release/RepRapFirmware-1.00i-dc42.bin b/Release/RepRapFirmware-1.00i-dc42.bin new file mode 100644 index 0000000..37129fc Binary files /dev/null and b/Release/RepRapFirmware-1.00i-dc42.bin differ diff --git a/RepRapFirmware.cpp b/RepRapFirmware.cpp index 773268c..ce88e2c 100644 --- a/RepRapFirmware.cpp +++ b/RepRapFirmware.cpp @@ -243,13 +243,13 @@ void RepRap::Init() while (initialisingInProgress) { Spin(); - if(gCodes->PrintingAFile()) + if(gCodes->DoingFileMacro()) { runningTheFile = true; } if(runningTheFile) { - if(!gCodes->PrintingAFile()) + if(!gCodes->DoingFileMacro()) { initialisingInProgress = false; } @@ -622,7 +622,7 @@ void RepRap::GetStatusResponse(StringRef& response, uint8_t type, bool forWebser // Paused / Stopped ch = 'S'; } - else if (gCodes->PrintingAFile()) + else if (gCodes->PrintingAFile() && !gCodes->DoingFileMacro()) { // Printing ch = 'P'; @@ -1106,6 +1106,12 @@ void RepRap::GetLegacyStatusResponse(StringRef& response, uint8_t type, int seq) response.catf(",\"buff\":%u", webserver->GetGcodeBufferSpace()); // send the amount of buffer space available for gcodes } + if (type == 2 && gCodes->PrintingAFile()) + { + // Send estimated times left bBased on file progress, filament usage, and layers + response.catf(",\"timesLeft\":[%.1f,%.1f,%.1f]", EstimateTimeLeft(0), EstimateTimeLeft(1), EstimateTimeLeft(2)); + } + if (type < 2 || (seq != -1 && replySeq > seq)) { response.catf(",\"seq\":%u", replySeq); // send the response sequence number diff --git a/Webserver.h b/Webserver.h index 505016e..235b0de 100644 --- a/Webserver.h +++ b/Webserver.h @@ -44,7 +44,7 @@ const unsigned int maxCommandWords = 4; // max number of space-separated words const unsigned int maxQualKeys = 5; // max number of key/value pairs in the qualifier const unsigned int maxHeaders = 10; // max number of key/value pairs in the headers -const unsigned int jsonReplyLength = 1024; // size of buffer used to hold JSON reply +const unsigned int jsonReplyLength = 2000; // size of buffer used to hold JSON reply const unsigned int maxSessions = 8; // maximum number of simultaneous HTTP sessions const unsigned int httpSessionTimeout = 30; // HTTP session timeout in seconds