diff options
author | David Crocker <dcrocker@eschertech.com> | 2017-01-03 12:49:48 +0300 |
---|---|---|
committer | David Crocker <dcrocker@eschertech.com> | 2017-01-03 12:50:33 +0300 |
commit | 660e9c7d1ca95df5e31693734c018172f2bae7d8 (patch) | |
tree | 2fdb6c72235ae9b2a3d4b44dd7877ac1cdf4323a | |
parent | 8533302849f1f93a65fe072e679afe5dd0497eb0 (diff) |
Version 1.17a
Homing speed:
- The speed factor (M220 command, or speed control in DWC and PanelDue)
no longer affects the speed of homing moves or other special moves (i.e.
G1 commands with S1 or S2 parameter)
Bug fixes:
- Fixed the M120 (Push)
command
- Setting relative extruder movement (M83) or a feed rate (G1
Fxxx) in config.g now works again
- The F (feed rate) parameter is now
processed correctly on a G1 command with the R parameter
- If you used
M106 to change a fan PWM frequency, the change did not take place until
you next changed the speed
- On boards with SAM3X processors, due to a
chip bug the fan speed was sometimes incorrect if you changed the PWM
frequency
- If an http client requested a non-existent file that was not
an HTML file, the server incorrectly returned a 404 HTML page
25 files changed, 268 insertions, 177 deletions
diff --git a/Release/Duet-0.6-0.8.5/Stable/DuetWebControl-1.14-b4.zip b/Release/Duet-0.6-0.8.5/Stable/DuetWebControl-1.14-RC1.zip Binary files differindex 21a5a602..0521c3dd 100644 --- a/Release/Duet-0.6-0.8.5/Stable/DuetWebControl-1.14-b4.zip +++ b/Release/Duet-0.6-0.8.5/Stable/DuetWebControl-1.14-RC1.zip diff --git a/Release/Duet-0.6-0.8.5/Stable/RepRapFirmware-1.17a.bin b/Release/Duet-0.6-0.8.5/Stable/RepRapFirmware-1.17a.bin Binary files differnew file mode 100644 index 00000000..d2f064d6 --- /dev/null +++ b/Release/Duet-0.6-0.8.5/Stable/RepRapFirmware-1.17a.bin diff --git a/Release/Duet-WiFi/Stable/DuetWebControl-1.14-b4.bin b/Release/Duet-WiFi/Stable/DuetWebControl-1.14-RC1.bin Binary files differindex 31bfb5e8..261ea7c0 100644 --- a/Release/Duet-WiFi/Stable/DuetWebControl-1.14-b4.bin +++ b/Release/Duet-WiFi/Stable/DuetWebControl-1.14-RC1.bin diff --git a/Release/Duet-WiFi/Stable/DuetWiFiFirmware-1.17a.bin b/Release/Duet-WiFi/Stable/DuetWiFiFirmware-1.17a.bin Binary files differnew file mode 100644 index 00000000..6c8f47c7 --- /dev/null +++ b/Release/Duet-WiFi/Stable/DuetWiFiFirmware-1.17a.bin diff --git a/Release/RADDS/Edge/RepRapFirmware-RADDS-1.17a.bin b/Release/RADDS/Edge/RepRapFirmware-RADDS-1.17a.bin Binary files differnew file mode 100644 index 00000000..52507c43 --- /dev/null +++ b/Release/RADDS/Edge/RepRapFirmware-RADDS-1.17a.bin diff --git a/src/Configuration.h b/src/Configuration.h index 06186fdb..14ecfe0d 100644 --- a/src/Configuration.h +++ b/src/Configuration.h @@ -43,10 +43,6 @@ const float ABS_ZERO = -273.15; // Celsius const float NEARLY_ABS_ZERO = -273.0; // Celsius const float ROOM_TEMPERATURE = 21.0; // Celsius -const float INCH_TO_MM = 25.4; -const float MINUTES_TO_SECONDS = 60.0; -const float SECONDS_TO_MINUTES = 1.0 / MINUTES_TO_SECONDS; - const float LONG_TIME = 300.0; // Seconds const float MINIMUM_TOOL_WARNING_INTERVAL = 4.0; // Seconds diff --git a/src/DuetNG/DuetEthernet/Network.cpp b/src/DuetNG/DuetEthernet/Network.cpp index 1a2298d7..db79de62 100644 --- a/src/DuetNG/DuetEthernet/Network.cpp +++ b/src/DuetNG/DuetEthernet/Network.cpp @@ -351,31 +351,17 @@ void Network::CloseDataPort() bool Network::AcquireFTPTransaction() { - return AcquireTransaction(FtpSocketNumber); + return sockets[FtpSocketNumber].AcquireTransaction(); } bool Network::AcquireDataTransaction() { - return AcquireTransaction(FtpDataSocketNumber); + return sockets[FtpDataSocketNumber].AcquireTransaction(); } bool Network::AcquireTelnetTransaction() { - return AcquireTransaction(TelnetSocketNumber); -} - -bool Network::AcquireTransaction(SocketNumber skt) -{ - if ( sockets[skt].GetTransaction() != nullptr - && sockets[skt].GetTransaction()->GetStatus() != TransactionStatus::sending - && sockets[skt].GetTransaction()->GetStatus() != TransactionStatus::finished - ) - { - currentTransactionSocketNumber = skt; - return true; - } - - return false; + return sockets[TelnetSocketNumber].AcquireTransaction(); } void Network::InitSockets() diff --git a/src/DuetNG/DuetEthernet/Network.h b/src/DuetNG/DuetEthernet/Network.h index d6d38555..1a479a40 100644 --- a/src/DuetNG/DuetEthernet/Network.h +++ b/src/DuetNG/DuetEthernet/Network.h @@ -88,8 +88,6 @@ private: active }; - bool AcquireTransaction(SocketNumber skt); - void InitSockets(); void TerminateSockets(); diff --git a/src/DuetNG/DuetEthernet/NetworkTransaction.cpp b/src/DuetNG/DuetEthernet/NetworkTransaction.cpp index eeeb0e90..f6fa3a76 100644 --- a/src/DuetNG/DuetEthernet/NetworkTransaction.cpp +++ b/src/DuetNG/DuetEthernet/NetworkTransaction.cpp @@ -235,11 +235,11 @@ const uint8_t *NetworkTransaction::GetDataToSend(size_t& length) void NetworkTransaction::Commit(bool keepConnectionAlive) { closeAfterSending = !keepConnectionAlive; - status = TransactionStatus::sending; - if (closeAfterSending) + if (sendBuffer == nullptr) { - cs->DiscardReceivedData(); + sendBuffer = sendStack->Pop(); } + status = TransactionStatus::sending; } // Call this to perform some networking tasks while processing deferred requests, diff --git a/src/DuetNG/DuetEthernet/NetworkTransaction.h b/src/DuetNG/DuetEthernet/NetworkTransaction.h index 0dd5c3cc..caacd051 100644 --- a/src/DuetNG/DuetEthernet/NetworkTransaction.h +++ b/src/DuetNG/DuetEthernet/NetworkTransaction.h @@ -47,6 +47,7 @@ public: TransactionStatus GetStatus() const { return status; } bool IsConnected() const; bool IsSending() const; + bool CloseAfterSending() const { return closeAfterSending; } bool HasMoreDataToRead() const; bool Read(char& b); diff --git a/src/DuetNG/DuetEthernet/Socket.cpp b/src/DuetNG/DuetEthernet/Socket.cpp index 045b76a1..feba6b73 100644 --- a/src/DuetNG/DuetEthernet/Socket.cpp +++ b/src/DuetNG/DuetEthernet/Socket.cpp @@ -9,12 +9,15 @@ #include "NetworkTransaction.h" #include "NetworkBuffer.h" +#include "Network.h" +#include "RepRap.h" +#include "Webserver.h" #include "socketlib.h" //*************************************************************************************************** // Socket class -Socket::Socket() : currentTransaction(nullptr), receivedData(nullptr) +Socket::Socket() : currentTransaction(nullptr), receivedData(nullptr), state(SocketState::inactive) { } @@ -38,12 +41,11 @@ void Socket::ReInit() persistConnection = true; isTerminated = false; isSending = false; + needTransaction = false; state = SocketState::inactive; // Re-initialise the socket on the W5500 -//debugPrintf("About to initialise socket %u\n", socketNum); socket(socketNum, Sn_MR_TCP, localPort, 0x00); -//debugPrintf("Initialised socket %u\n", socketNum); } // Close a connection when the last packet has been sent @@ -152,6 +154,7 @@ void Socket::Poll(bool full) if (localPort != 0) // localPort for the FTP data socket is 0 until we have decided what port number to use { ExecCommand(socketNum, Sn_CR_LISTEN); + state = SocketState::listening; } break; @@ -167,40 +170,57 @@ void Socket::Poll(bool full) setSn_IR(socketNum, Sn_IR_CON); } - // See if the socket has received any data + if (state == SocketState::listening) // if it is a new connection { + needTransaction = false; + if (socketNum == FtpSocketNumber || socketNum == TelnetSocketNumber) + { + // FTP and Telnet protocols need a connection reply, so tell the Webserver module about the new connection + if (currentTransaction == nullptr) + { + currentTransaction = NetworkTransaction::Allocate(); + if (currentTransaction != nullptr) + { + currentTransaction->Set(this, TransactionStatus::connected); + } + } + else + { + // This should not happen + debugPrintf("ERROR:currentTransation should be null but isn't\n"); + } + } + state = SocketState::connected; + } + + { + // See if the socket has received any data const uint16_t len = getSn_RX_RSR(socketNum); if (len != 0) { // debugPrintf("%u available\n", len); // There is data available, so allocate a buffer + //TODO: if there is already a buffer and it is in an appropriate state (i.e. receiving) and it has enough room, we could just append the data NetworkBuffer * const buf = NetworkBuffer::Allocate(); if (buf != nullptr) { - const int32_t ret = recv(socketNum, buf->Data(), min<size_t>(len, NetworkBuffer::bufferSize)); -// debugPrintf("ret %d\n", ret); - if (ret > 0) - { - buf->dataLength = (size_t)ret; - buf->readPointer = 0; - NetworkBuffer::AppendToList(&receivedData, buf); - } - else - { - buf->Release(); -// debugPrintf("Bad receive, code = %d\n", ret); - } + wiz_recv_data(socketNum, buf->Data(), len); + ExecCommand(socketNum, Sn_CR_RECV); + buf->dataLength = (size_t)len; + buf->readPointer = 0; + NetworkBuffer::AppendToList(&receivedData, buf); } - else debugPrintf("no buffer\n"); +// else debugPrintf("no buffer\n"); } + } - if (receivedData != nullptr && currentTransaction == nullptr) + if (currentTransaction == nullptr && (receivedData != nullptr || needTransaction)) + { + currentTransaction = NetworkTransaction::Allocate(); + if (currentTransaction != nullptr) { - currentTransaction = NetworkTransaction::Allocate(); - if (currentTransaction != nullptr) - { - currentTransaction->Set(this, TransactionStatus::receiving); - } + currentTransaction->Set(this, (needTransaction) ? TransactionStatus::acquired : TransactionStatus::receiving); + needTransaction = false; } } @@ -209,8 +229,14 @@ void Socket::Poll(bool full) // We could use a buffer locking mechanism instead. However, the speed of sending is not critical, so we don't do that yet. if (full && IsSending() && TrySendData()) { + const bool closeAfterSending = currentTransaction->CloseAfterSending(); ReleaseTransaction(); - ExecCommand(socketNum, Sn_CR_DISCON); + if (closeAfterSending) + { + ExecCommand(socketNum, Sn_CR_DISCON); + state = SocketState::closing; + DiscardReceivedData(); + } } break; @@ -218,10 +244,30 @@ void Socket::Poll(bool full) #ifdef _HTTPSERVER_DEBUG_ printf("> HTTPSocket[%d] : ClOSE_WAIT\r\n", socketNum); #endif - if (!IsSending() || TrySendData()) + state = SocketState::clientDisconnecting; + if (IsSending() && TrySendData()) { - ReleaseTransaction(); - ExecCommand(socketNum, Sn_CR_DISCON); + ReleaseTransaction(); // finished sending + } + + // Although there is a transaction status for a client disconnecting, the webserver module does nothing with those transactions. + // So we don't bother to generate them here. + if (!IsSending() && currentTransaction == nullptr) + { + if (HasMoreDataToRead()) + { + // We have more received data, so make it available to the webserver to process + currentTransaction = NetworkTransaction::Allocate(); + if (currentTransaction != nullptr) + { + currentTransaction->Set(this, TransactionStatus::receiving); + } + } + else + { + ExecCommand(socketNum, Sn_CR_DISCON); + state = SocketState::closing; + } } break; @@ -229,7 +275,10 @@ void Socket::Poll(bool full) #ifdef _HTTPSERVER_DEBUG_ printf("> HTTPSocket[%d] : CLOSED\r\n", s); #endif - if (socket(socketNum, Sn_MR_TCP, localPort, 0x00) == socketNum) // Reinitialize the socket + reprap.GetWebserver()->ConnectionLost(this); // the webserver needs this to be called for both graceful and disgraceful disconnects + state = SocketState::inactive; + + if (socket(socketNum, Sn_MR_TCP, localPort, 0x00) == socketNum) // Reinitialize the socket { #ifdef _HTTPSERVER_DEBUG_ printf("> HTTPSocket[%d] : OPEN\r\n", socketNum); @@ -295,6 +344,7 @@ bool Socket::TrySendData() ptr += (uint16_t)length; sent = true; } + if (sent) { //debugPrintf("Sending data, rp=%04x tp=%04x\n", getSn_TX_RD(socketNum), getSn_TX_WR(socketNum)); @@ -318,4 +368,22 @@ void Socket::DiscardReceivedData() } } +// The webserver calls this to tell the socket that it needs a transaction, e.g. for sending a Telnet os FTP response. +// An empty transaction will do. +// Return true if we can do it, false if the connection is closed or closing. +bool Socket::AcquireTransaction() +{ + if (currentTransaction != nullptr && currentTransaction->GetStatus() == TransactionStatus::acquired) + { + return true; + } + + if (getSn_SR(socketNum) == SOCK_ESTABLISHED) + { + needTransaction = true; + return true; + } + return false; +} + // End diff --git a/src/DuetNG/DuetEthernet/Socket.h b/src/DuetNG/DuetEthernet/Socket.h index 7c6ef596..c37a4e82 100644 --- a/src/DuetNG/DuetEthernet/Socket.h +++ b/src/DuetNG/DuetEthernet/Socket.h @@ -34,16 +34,16 @@ public: bool IsPersistentConnection() const { return persistConnection; } bool CanWrite() const; void DiscardReceivedData(); + bool AcquireTransaction(); private: enum class SocketState : uint8_t { inactive, - idle, - requestInProgress, - requestDone, - responseInProgress, - responseDone + listening, + connected, + clientDisconnecting, + closing }; void ReInit(); @@ -60,7 +60,8 @@ private: bool isTerminated; // Will be true if the connection has gone down unexpectedly (TCP RST) SocketNumber socketNum; // The W5500 socket number we are using SocketState state; - bool isSending; + bool isSending; // True if we have written data to the W5500 to send and have not yet seen success or timeout + bool needTransaction; // True if the web server has asked for a transaction }; #endif /* SRC_DUETNG_DUETETHERNET_SOCKET_H_ */ diff --git a/src/DuetNG/DuetEthernet/Wiznet/Ethernet/socketlib.cpp b/src/DuetNG/DuetEthernet/Wiznet/Ethernet/socketlib.cpp index b1d60e4b..84b48433 100644 --- a/src/DuetNG/DuetEthernet/Wiznet/Ethernet/socketlib.cpp +++ b/src/DuetNG/DuetEthernet/Wiznet/Ethernet/socketlib.cpp @@ -55,7 +55,7 @@ //***************************************************************************** #include <socketlib.h> -#define _SOCKET_DEBUG_ +//#define _SOCKET_DEBUG_ #ifdef _SOCKET_DEBUG_ extern "C" void debugPrintf(const char *fmt, ...); @@ -65,8 +65,6 @@ extern "C" void delay(uint32_t); # define DEBUG_PRINTF(_fmt, ...) #endif - - #define SOCK_ANY_PORT_NUM 0xC000 static uint16_t sock_any_port = SOCK_ANY_PORT_NUM; diff --git a/src/DuetNG/DuetEthernet/Wiznet/Internet/DHCP/dhcp.cpp b/src/DuetNG/DuetEthernet/Wiznet/Internet/DHCP/dhcp.cpp index 2d42feb0..c385c68b 100644 --- a/src/DuetNG/DuetEthernet/Wiznet/Internet/DHCP/dhcp.cpp +++ b/src/DuetNG/DuetEthernet/Wiznet/Internet/DHCP/dhcp.cpp @@ -55,7 +55,7 @@ /* If you want to display debug & processing message, Define _DHCP_DEBUG_ in dhcp.h */ -#define _DHCP_DEBUG_ +//#define _DHCP_DEBUG_ #ifdef _DHCP_DEBUG_ extern "C" void debugPrintf(const char *fmt, ...); diff --git a/src/DuetNG/DuetWiFi/Webserver.cpp b/src/DuetNG/DuetWiFi/Webserver.cpp index 7d16d3a4..4b290ed9 100644 --- a/src/DuetNG/DuetWiFi/Webserver.cpp +++ b/src/DuetNG/DuetWiFi/Webserver.cpp @@ -661,11 +661,11 @@ bool Webserver::ProcessFirstFragment(HttpSession& session, const char* command, if (StringEquals(command, "move")) { const char* response = "{\"err\":1}"; // assume failure - const char* oldVal = GetKeyValue("old"); - const char* newVal = GetKeyValue("new"); + const char* const oldVal = GetKeyValue("old"); + const char* const newVal = GetKeyValue("new"); if (oldVal != nullptr && newVal != nullptr) { - bool success = platform->GetMassStorage()->Rename(oldVal, newVal); + const bool success = platform->GetMassStorage()->Rename(oldVal, newVal); if (success) { response = "{\"err\":0}"; @@ -756,13 +756,13 @@ bool Webserver::ProcessFirstFragment(HttpSession& session, const char* command, { dir = platform->GetGCodeDir(); } - const char* flagDirsVal = GetKeyValue("flagDirs"); - bool flagDirs = flagDirsVal != nullptr && atoi(flagDirsVal) == 1; + const char* const flagDirsVal = GetKeyValue("flagDirs"); + const bool flagDirs = flagDirsVal != nullptr && atoi(flagDirsVal) == 1; response = reprap.GetFilesResponse(dir, flagDirs); } else if (StringEquals(command, "fileinfo")) { - const char* nameVal = GetKeyValue("name"); + const char* const nameVal = GetKeyValue("name"); if (reprap.GetPrintMonitor()->GetFileInfoResponse(nameVal, response)) { processingDeferredRequest = false; diff --git a/src/Fan.cpp b/src/Fan.cpp index 67206112..bd29b965 100644 --- a/src/Fan.cpp +++ b/src/Fan.cpp @@ -20,7 +20,7 @@ void Fan::Init(Pin p_pin, bool hwInverted) inverted = blipping = false; heatersMonitored = 0; triggerTemperature = HOT_END_FAN_TEMPERATURE; - lastPwm = -1.0; + lastPwm = -1.0; // force a refresh Refresh(); } @@ -62,6 +62,8 @@ void Fan::SetInverted(bool inv) Refresh(); } +// Set the hardware PWM +// If you want make sure that the PWM is definitely updated, set lastPWM negative before calling this void Fan::SetHardwarePwm(float pwmVal) { if (pin != NoPin) @@ -88,6 +90,7 @@ void Fan::SetHardwarePwm(float pwmVal) void Fan::SetPwmFrequency(float p_freq) { freq = (uint16_t)constrain<float>(p_freq, 1.0, 65535.0); + lastPwm = -1.0; // force the PWM to be updated Refresh(); } @@ -97,6 +100,8 @@ void Fan::SetHeatersMonitored(uint16_t h) Refresh(); } +// Refresh the fan PWM +// If you want make sure that the PWM is definitely updated, set lastPWM negative before calling this void Fan::Refresh() { float reqVal = (heatersMonitored == 0) @@ -139,6 +144,7 @@ void Fan::Disable() if (pin != NoPin) { inverted = false; + lastPwm = -1; SetHardwarePwm(0.0); } pin = NoPin; diff --git a/src/GCodes/GCodeMachineState.h b/src/GCodes/GCodeMachineState.h index eec66ebc..76943162 100644 --- a/src/GCodes/GCodeMachineState.h +++ b/src/GCodes/GCodeMachineState.h @@ -66,6 +66,14 @@ public: static GCodeMachineState *Allocate() post(!result.IsLive(); result.state == GCodeState::normal); + // Copy values that may have been altered by config.g into this state record + void CopyStateFrom(const GCodeMachineState& other) + { + drivesRelative = other.drivesRelative; + axesRelative = other.axesRelative; + feedrate = other.feedrate; + } + static void Release(GCodeMachineState *ms); static unsigned int GetNumAllocated() { return numAllocated; } static unsigned int GetNumInUse(); diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp index 1023b08a..73e4c1e2 100644 --- a/src/GCodes/GCodes.cpp +++ b/src/GCodes/GCodes.cpp @@ -55,7 +55,7 @@ void GCodes::RestorePoint::Init() { moveCoords[i] = 0.0; } - feedRate = DefaultFeedrate/minutesToSeconds; + feedRate = DefaultFeedrate * secondsToMinutes; } GCodes::GCodes(Platform* p, Webserver* w) : @@ -92,6 +92,7 @@ void GCodes::Init() eofStringCounter = 0; eofStringLength = strlen(eofString); offSetSet = false; + runningConfigFile = false; active = true; longWait = platform->Time(); dwellTime = longWait; @@ -132,7 +133,7 @@ void GCodes::Reset() probeCount = 0; cannedCycleMoveCount = 0; cannedCycleMoveQueued = false; - speedFactor = 1.0 / minutesToSeconds; // default is just to convert from mm/minute to mm/second + speedFactor = secondsToMinutes; // default is just to convert from mm/minute to mm/second for (size_t i = 0; i < MaxExtruders; ++i) { extrusionFactors[i] = 1.0; @@ -184,7 +185,8 @@ float GCodes::FractionOfFilePrinted() const // We use triggerCGode as the source to prevent any triggers being executed until we have finished bool GCodes::RunConfigFile(const char* fileName) { - return DoFileMacro(*daemonGCode, fileName, false); + runningConfigFile = DoFileMacro(*daemonGCode, fileName, false); + return runningConfigFile; } // Return true if the daemon is busy running config.g or a trigger file @@ -193,6 +195,15 @@ bool GCodes::IsDaemonBusy() const return daemonGCode->MachineState().fileState.IsLive(); } +// Copy the feed rate etc. from the daemon to the input channels +void GCodes::CopyConfigFinalValues(GCodeBuffer& gb) +{ + for (size_t i = 0; i < ARRAY_SIZE(gcodeSources); ++i) + { + gcodeSources[i]->MachineState().CopyStateFrom(gb.MachineState()); + } +} + void GCodes::Spin() { if (!active) @@ -333,7 +344,7 @@ void GCodes::Spin() { moveBuffer.coords[drive] = 0.0; } - moveBuffer.feedRate = DefaultFeedrate/minutesToSeconds; // ask for a good feed rate, we may have paused during a slow move + moveBuffer.feedRate = DefaultFeedrate * secondsToMinutes; // ask for a good feed rate, we may have paused during a slow move moveBuffer.moveType = 0; moveBuffer.endStopsToCheck = 0; moveBuffer.usePressureAdvance = false; @@ -741,7 +752,12 @@ void GCodes::DoFilePrint(GCodeBuffer& gb, StringRef& reply) } else { - // Finished a macro + // Finished a macro or finished processing config.g + if (runningConfigFile) + { + CopyConfigFinalValues(gb); + runningConfigFile = false; + } Pop(gb); gb.Init(); if (gb.GetState() == GCodeState::normal) @@ -957,14 +973,17 @@ unsigned int GCodes::LoadMoveBufferFromGCode(GCodeBuffer& gb, int moveType) } // Deal with feed rate - if (gb.Seen(feedrateLetter)) + if (moveType >= 0 && gb.Seen(feedrateLetter)) { - gb.MachineState().feedrate = gb.GetFValue() * distanceScale * speedFactor; + const float rate = gb.GetFValue() * distanceScale; + gb.MachineState().feedrate = (moveType == 0) + ? rate * speedFactor + : rate * secondsToMinutes; // don't apply the speed factor to homing and other special moves } moveBuffer.feedRate = gb.MachineState().feedrate; // First do extrusion, and check, if we are extruding, that we have a tool to extrude with - Tool* tool = reprap.GetCurrentTool(); + Tool* const tool = reprap.GetCurrentTool(); if (gb.Seen(extrudeLetter)) { if (tool == nullptr) @@ -972,7 +991,7 @@ unsigned int GCodes::LoadMoveBufferFromGCode(GCodeBuffer& gb, int moveType) platform->Message(GENERIC_MESSAGE, "Attempting to extrude with no tool selected.\n"); return 0; } - size_t eMoveCount = tool->DriveCount(); + const size_t eMoveCount = tool->DriveCount(); if (eMoveCount > 0) { // Set the drive values for this tool. @@ -1485,7 +1504,7 @@ bool GCodes::OffsetAxes(GCodeBuffer& gb) if (gb.Seen(feedrateLetter)) // Has the user specified a feedrate? { - cannedFeedRate = gb.GetFValue() * distanceScale * SECONDS_TO_MINUTES; + cannedFeedRate = gb.GetFValue() * distanceScale * secondsToMinutes; } else { diff --git a/src/GCodes/GCodes.h b/src/GCodes/GCodes.h index 5aaea8ce..77252d3f 100644 --- a/src/GCodes/GCodes.h +++ b/src/GCodes/GCodes.h @@ -77,36 +77,36 @@ public: bool canPauseAfter; // true if we can pause just after this move and successfully restart }; - GCodes(Platform* p, Webserver* w); - void Spin(); // Called in a tight loop to make this class work - void Init(); // Set it up - void Exit(); // Shut it down - void Reset(); // Reset some parameter to defaults - bool ReadMove(RawMove& m); // Called by the Move class to get a movement set by the last G Code - void ClearMove(); - void QueueFileToPrint(const char* fileName); // Open a file of G Codes to run - void DeleteFile(const char* fileName); // Does what it says - void GetCurrentCoordinates(StringRef& s) const; // Write where we are into a string - bool DoingFileMacro() const; // Or still busy processing a macro file? - float FractionOfFilePrinted() const; // Get fraction of file printed - void Diagnostics(MessageType mtype); // Send helpful information out - - bool RunConfigFile(const char* fileName); // Start running the config file - bool IsDaemonBusy() const; // Return true if the daemon is busy running config.g or a trigger file + GCodes(Platform* p, Webserver* w); + void Spin(); // Called in a tight loop to make this class work + void Init(); // Set it up + void Exit(); // Shut it down + void Reset(); // Reset some parameter to defaults + bool ReadMove(RawMove& m); // Called by the Move class to get a movement set by the last G Code + void ClearMove(); + void QueueFileToPrint(const char* fileName); // Open a file of G Codes to run + void DeleteFile(const char* fileName); // Does what it says + void GetCurrentCoordinates(StringRef& s) const; // Write where we are into a string + bool DoingFileMacro() const; // Or still busy processing a macro file? + float FractionOfFilePrinted() const; // Get fraction of file printed + void Diagnostics(MessageType mtype); // Send helpful information out + + bool RunConfigFile(const char* fileName); // Start running the config file + bool IsDaemonBusy() const; // Return true if the daemon is busy running config.g or a trigger file bool GetAxisIsHomed(unsigned int axis) const // Has the axis been homed? - { return (axesHomed & (1 << axis)) != 0; } - void SetAxisIsHomed(unsigned int axis) // Tell us that the axis is now homed - { axesHomed |= (1 << axis); } - void SetAxisNotHomed(unsigned int axis) // Tell us that the axis is not homed - { axesHomed &= ~(1 << axis); } - - float GetSpeedFactor() const { return speedFactor * minutesToSeconds; } // Return the current speed factor - float GetExtrusionFactor(size_t extruder) { return extrusionFactors[extruder]; } // Return the current extrusion factors - float GetRawExtruderPosition(size_t drive) const; // Get the actual extruder position, after adjusting the extrusion factor - float GetRawExtruderTotalByDrive(size_t extruder) const; // Get the total extrusion since start of print, for one drive - float GetTotalRawExtrusion() const { return rawExtruderTotal; } // Get the total extrusion since start of print, all drives - + { return (axesHomed & (1 << axis)) != 0; } + void SetAxisIsHomed(unsigned int axis) // Tell us that the axis is now homed + { axesHomed |= (1 << axis); } + void SetAxisNotHomed(unsigned int axis) // Tell us that the axis is not homed + { axesHomed &= ~(1 << axis); } + + float GetSpeedFactor() const { return speedFactor * minutesToSeconds; } // Return the current speed factor + float GetExtrusionFactor(size_t extruder) { return extrusionFactors[extruder]; } // Return the current extrusion factors + float GetRawExtruderPosition(size_t drive) const; // Get the actual extruder position, after adjusting the extrusion factor + float GetRawExtruderTotalByDrive(size_t extruder) const; // Get the total extrusion since start of print, for one drive + float GetTotalRawExtrusion() const { return rawExtruderTotal; } // Get the total extrusion since start of print, all drives + bool IsFlashing() const { return isFlashing; } // Is a new firmware binary going to be flashed? bool IsPaused() const; @@ -114,16 +114,16 @@ public: bool IsResuming() const; bool IsRunning() const; - bool AllAxesAreHomed() const; // Return true if all axes are homed + bool AllAxesAreHomed() const; // Return true if all axes are homed - void CancelPrint(); // Cancel the current print + void CancelPrint(); // Cancel the current print - void MoveStoppedByZProbe() { zProbeTriggered = true; } // Called from the step ISR when the Z probe is triggered, causing the move to be aborted + void MoveStoppedByZProbe() { zProbeTriggered = true; } // Called from the step ISR when the Z probe is triggered, causing the move to be aborted - size_t GetNumAxes() const { return numAxes; } - size_t GetNumExtruders() const { return numExtruders; } + size_t GetNumAxes() const { return numAxes; } + size_t GetNumExtruders() const { return numExtruders; } - static const char axisLetters[MAX_AXES]; // 'X', 'Y', 'Z' + static const char axisLetters[MAX_AXES]; // 'X', 'Y', 'Z' private: enum class CannedMoveType : uint8_t { none, relative, absolute }; @@ -219,6 +219,7 @@ private: void ClearHeightMap() const; // Clear the height map bool WriteConfigOverrideFile(StringRef& reply, const char *fileName) const; // Write the config-override file + void CopyConfigFinalValues(GCodeBuffer& gb); // Copy the feed rate etc. from the daemon to the input channels static uint32_t LongArrayToBitMap(const long *arr, size_t numEntries); // Convert an array of longs to a bit map @@ -240,6 +241,7 @@ private: bool active; // Live and running? bool isPaused; // true if the print has been paused bool dwellWaiting; // We are in a dwell + bool runningConfigFile; // We are running config.g during the startup process unsigned int segmentsLeft; // The number of segments left to do in the current move, or 0 if no move available float dwellTime; // How long a pause for a dwell (seconds)? RawMove moveBuffer; // Move details to pass to Move class diff --git a/src/GCodes/GCodes2.cpp b/src/GCodes/GCodes2.cpp index e8a9131d..efdf175c 100644 --- a/src/GCodes/GCodes2.cpp +++ b/src/GCodes/GCodes2.cpp @@ -114,7 +114,7 @@ bool GCodes::HandleGcode(GCodeBuffer& gb, StringRef& reply) { moveBuffer.coords[drive] = 0.0; } - moveBuffer.feedRate = (gb.Seen(feedrateLetter)) ? gb.GetFValue() : gb.MachineState().feedrate; + moveBuffer.feedRate = (gb.Seen(feedrateLetter)) ? gb.GetFValue() * secondsToMinutes : gb.MachineState().feedrate; moveBuffer.filePos = noFilePosition; moveBuffer.usePressureAdvance = false; segmentsLeft = 1; @@ -162,7 +162,7 @@ bool GCodes::HandleGcode(GCodeBuffer& gb, StringRef& reply) break; case 20: // Inches (which century are we living in, here?) - distanceScale = INCH_TO_MM; + distanceScale = InchToMm; break; case 21: // mm @@ -1673,7 +1673,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, StringRef& reply) case 220: // Set/report speed factor override percentage if (gb.Seen('S')) { - float newSpeedFactor = (gb.GetFValue() / 100.0) * secondsToMinutes; // include the conversion from mm/minute to mm/second + float newSpeedFactor = (gb.GetFValue() * 0.01) * secondsToMinutes; // include the conversion from mm/minute to mm/second if (newSpeedFactor > 0.0) { gb.MachineState().feedrate *= newSpeedFactor / speedFactor; diff --git a/src/Platform.cpp b/src/Platform.cpp index 3e9cd452..17d97f76 100644 --- a/src/Platform.cpp +++ b/src/Platform.cpp @@ -1351,9 +1351,9 @@ void Platform::Diagnostics(MessageType mtype) MessageF(mtype, "Recycled dynamic ram: %d\n", mi.fordblks); uint32_t currentStack, maxStack, neverUsed; GetStackUsage(¤tStack, &maxStack, &neverUsed); - MessageF(mtype, "Current stack ram used: %d\n", currentStack); - MessageF(mtype, "Maximum stack ram used: %d\n", maxStack); - MessageF(mtype, "Never used ram: %d\n", neverUsed); + MessageF(mtype, "Current stack ram used: %u\n", currentStack); + MessageF(mtype, "Maximum stack ram used: %u\n", maxStack); + MessageF(mtype, "Never used ram: %u\n", neverUsed); // Show the up time and reason for the last reset const uint32_t now = (uint32_t)Time(); // get up time in seconds @@ -1404,6 +1404,11 @@ void Platform::Diagnostics(MessageType mtype) // Show the current error codes MessageF(mtype, "Error status: %u\n", errorCodeBits); + //***TEMPORARY show the maximum PWM loop count, which should never exceed 1 + extern uint32_t maxPwmLoopCount; + MessageF(mtype, "Max PWM loop count %u\n", maxPwmLoopCount); + maxPwmLoopCount = 0; + // Show the number of free entries in the file table unsigned int numFreeFiles = 0; for (size_t i = 0; i < MAX_FILES; i++) @@ -1524,15 +1529,12 @@ void Platform::DiagnosticTest(int d) } } +extern "C" uint32_t _estack; // this is defined in the linker script + // Return the stack usage and amount of memory that has never been used, in bytes void Platform::GetStackUsage(uint32_t* currentStack, uint32_t* maxStack, uint32_t* neverUsed) const { - const char * const ramend = (const char *) -#if SAM4E - IRAM_ADDR + IRAM_SIZE; -#else - IRAM0_ADDR + IRAM_SIZE; -#endif + const char * const ramend = (const char *)&_estack; register const char * stack_ptr asm ("sp"); const char * const heapend = sbrk(0); const char * stack_lwm = heapend; diff --git a/src/RepRapFirmware.h b/src/RepRapFirmware.h index 03783fb6..1b866008 100644 --- a/src/RepRapFirmware.h +++ b/src/RepRapFirmware.h @@ -93,6 +93,7 @@ const float minutesToSeconds = 60.0; const float secondsToMinutes = 1.0/minutesToSeconds; const float SecondsToMillis = 1000.0; const float MillisToSeconds = 0.001; +const float InchToMm = 25.4; // Type of an offset in a file typedef uint32_t FilePosition; diff --git a/src/Version.h b/src/Version.h index 98641268..7d12aff2 100644 --- a/src/Version.h +++ b/src/Version.h @@ -9,11 +9,11 @@ #define SRC_VERSION_H_ #ifndef VERSION -# define VERSION "1.17+2" +# define VERSION "1.17a" #endif #ifndef DATE -# define DATE "2016-12-29" +# define DATE "2017-01-02" #endif #define AUTHORS "reprappro, dc42, zpl, t3p3, dnewman" diff --git a/src/Webserver/Webserver.cpp b/src/Webserver/Webserver.cpp index 72e62ca2..9c11c4bc 100644 --- a/src/Webserver/Webserver.cpp +++ b/src/Webserver/Webserver.cpp @@ -621,7 +621,7 @@ void Webserver::HttpInterpreter::DoFastUpload() // Write data in sector-aligned chunks. This also means that the buffer in fatfs is only used to hold the FAT. // Buffer size must be a multiple of the 512b sector size. #ifdef DUET_NG - static const size_t writeBufLength = 4096; + static const size_t writeBufLength = 8192; #else static const size_t writeBufLength = 2048; #endif @@ -754,13 +754,8 @@ void Webserver::HttpInterpreter::SendFile(const char* nameOfFileToSend, bool isW fileToSend = platform->GetFileStore(FS_PREFIX, nameOfFileToSend, false); if (fileToSend == nullptr) { - nameOfFileToSend = FOUR04_PAGE_FILE; - fileToSend = platform->GetFileStore(platform->GetWebDir(), nameOfFileToSend, false); - if (fileToSend == nullptr) - { - RejectMessage("not found", 404); - return; - } + RejectMessage("not found", 404); + return; } transaction->SetFileToWrite(fileToSend); } @@ -914,11 +909,11 @@ void Webserver::HttpInterpreter::SendJsonResponse(const char* command) bool mayKeepOpen; if (numQualKeys == 0) { - GetJsonResponse(command, jsonResponse, "", "", 0, mayKeepOpen); + GetJsonResponse(command, jsonResponse, mayKeepOpen); } else { - GetJsonResponse(command, jsonResponse, qualifiers[0].key, qualifiers[0].value, qualifiers[1].key - qualifiers[0].value - 1, mayKeepOpen); + GetJsonResponse(command, jsonResponse, mayKeepOpen); } // Check special cases of deferred requests (rr_fileinfo) and rejected messages @@ -963,13 +958,13 @@ void Webserver::HttpInterpreter::SendJsonResponse(const char* command) // Get the Json response for this command. // 'value' is null-terminated, but we also pass its length in case it contains embedded nulls, which matters when uploading files. -void Webserver::HttpInterpreter::GetJsonResponse(const char* request, OutputBuffer *&response, const char* key, const char* value, size_t valueLength, bool& keepOpen) +void Webserver::HttpInterpreter::GetJsonResponse(const char* request, OutputBuffer *&response, bool& keepOpen) { keepOpen = false; // assume we don't want to persist the connection - if (StringEquals(request, "connect") && StringEquals(key, "password")) + if (StringEquals(request, "connect") && GetKeyValue("password") != nullptr) { - if (IsAuthenticated() || reprap.CheckPassword(value)) + if (IsAuthenticated() || reprap.CheckPassword(GetKeyValue("password"))) { // Password OK if (Authenticate()) @@ -1012,10 +1007,10 @@ void Webserver::HttpInterpreter::GetJsonResponse(const char* request, OutputBuff else if (StringEquals(request, "status")) { int type = 0; - if (StringEquals(key, "type")) + if (GetKeyValue("type") != nullptr) { // New-style JSON status responses - type = atoi(value); + type = atoi(GetKeyValue("type")); if (type < 1 || type > 3) { type = 1; @@ -1031,36 +1026,34 @@ void Webserver::HttpInterpreter::GetJsonResponse(const char* request, OutputBuff response = reprap.GetLegacyStatusResponse(1, 0); } } - else if (StringEquals(request, "gcode") && StringEquals(key, "gcode")) + else if (StringEquals(request, "gcode") && GetKeyValue("gcode") != nullptr) { - LoadGcodeBuffer(value); + LoadGcodeBuffer(GetKeyValue("gcode")); response->printf("{\"buff\":%u}", GetGCodeBufferSpace()); } else if (StringEquals(request, "upload")) { response->printf("{\"err\":%d}", (uploadedBytes == postFileLength) ? 0 : 1); } - else if (StringEquals(request, "delete") && StringEquals(key, "name")) + else if (StringEquals(request, "delete") && GetKeyValue("name") != nullptr) { - bool ok = platform->GetMassStorage()->Delete(FS_PREFIX, value); + bool ok = platform->GetMassStorage()->Delete(FS_PREFIX, GetKeyValue("name")); response->printf("{\"err\":%d}", (ok) ? 0 : 1); } - else if (StringEquals(request, "filelist")) + else if (StringEquals(request, "filelist") && GetKeyValue("dir") != nullptr) { OutputBuffer::Release(response); - response = reprap.GetFilelistResponse(value); + response = reprap.GetFilelistResponse(GetKeyValue("dir")); } else if (StringEquals(request, "files")) { - const char* dir = (StringEquals(key, "dir")) ? value : platform->GetGCodeDir(); - bool flagDirs = false; - if (numQualKeys >= 2) + const char* dir = GetKeyValue("dir"); + if (dir == nullptr) { - if (StringEquals(qualifiers[1].key, "flagDirs")) - { - flagDirs = StringEquals(qualifiers[1].value, "1"); - } + dir = platform->GetGCodeDir(); } + const char* const flagDirsVal = GetKeyValue("flagDirs"); + const bool flagDirs = flagDirsVal != nullptr && atoi(flagDirsVal) == 1; OutputBuffer::Release(response); response = reprap.GetFilesResponse(dir, flagDirs); } @@ -1073,10 +1066,11 @@ void Webserver::HttpInterpreter::GetJsonResponse(const char* request, OutputBuff } else { - if (StringEquals(qualifiers[0].key, "name")) + const char* const nameVal = GetKeyValue("name"); + if (nameVal != nullptr) { // Regular rr_fileinfo?name=xxx call - strncpy(filenameBeingProcessed, value, ARRAY_SIZE(filenameBeingProcessed)); + strncpy(filenameBeingProcessed, nameVal, ARRAY_SIZE(filenameBeingProcessed)); filenameBeingProcessed[ARRAY_UPB(filenameBeingProcessed)] = 0; } else @@ -1091,26 +1085,24 @@ void Webserver::HttpInterpreter::GetJsonResponse(const char* request, OutputBuff } else if (StringEquals(request, "move")) { - if (numQualKeys >= 2) + const char* const oldVal = GetKeyValue("old"); + const char* const newVal = GetKeyValue("new"); + bool success = false; + if (oldVal != nullptr && newVal != nullptr) { - if (StringEquals(key, "old") && StringEquals(qualifiers[1].key, "new")) - { - response->printf("{\"err\":%d}", platform->GetMassStorage()->Rename(value, qualifiers[1].value) ? 0 : 1); - } - else - { - response->printf("{\"err\":1}"); - } - } - else - { - response->printf("{\"err\":1}"); + success = platform->GetMassStorage()->Rename(oldVal, newVal); } + response->printf("{\"err\":%d}", (success) ? 0 : 1); } - else if (StringEquals(request, "mkdir") && StringEquals(key, "dir")) + else if (StringEquals(request, "mkdir")) { - bool ok = (platform->GetMassStorage()->MakeDirectory(value)); - response->printf("{\"err\":%d}", (ok) ? 0 : 1); + const char* dirVal = GetKeyValue("dir"); + bool success = false; + if (dirVal != nullptr) + { + success = (platform->GetMassStorage()->MakeDirectory(dirVal)); + } + response->printf("{\"err\":%d}", (success) ? 0 : 1); } else if (StringEquals(request, "config")) { @@ -1123,6 +1115,18 @@ void Webserver::HttpInterpreter::GetJsonResponse(const char* request, OutputBuff } } +const char* Webserver::HttpInterpreter::GetKeyValue(const char *key) const +{ + for (size_t i = 0; i < numQualKeys; ++i) + { + if (StringEquals(qualifiers[i].key, key)) + { + return qualifiers[i].value; + } + } + return nullptr; +} + void Webserver::HttpInterpreter::ResetState() { clientPointer = 0; diff --git a/src/Webserver/Webserver.h b/src/Webserver/Webserver.h index ef14bcab..3e4f2c30 100644 --- a/src/Webserver/Webserver.h +++ b/src/Webserver/Webserver.h @@ -199,7 +199,7 @@ protected: void SendFile(const char* nameOfFileToSend, bool isWebFile); void SendGCodeReply(); void SendJsonResponse(const char* command); - void GetJsonResponse(const char* request, OutputBuffer *&response, const char* key, const char* value, size_t valueLength, bool& keepOpen); + void GetJsonResponse(const char* request, OutputBuffer *&response, bool& keepOpen); bool ProcessMessage(); bool RejectMessage(const char* s, unsigned int code = 500); @@ -232,6 +232,7 @@ protected: bool IsAuthenticated() const; void UpdateAuthentication(); bool RemoveAuthentication(); + const char* GetKeyValue(const char *key) const; // return the value of the specified key, or nullptr if not present // Deal with incoming G-Codes |