Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Crocker <dcrocker@eschertech.com>2017-01-03 12:49:48 +0300
committerDavid Crocker <dcrocker@eschertech.com>2017-01-03 12:50:33 +0300
commit660e9c7d1ca95df5e31693734c018172f2bae7d8 (patch)
tree2fdb6c72235ae9b2a3d4b44dd7877ac1cdf4323a /src
parent8533302849f1f93a65fe072e679afe5dd0497eb0 (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
Diffstat (limited to 'src')
-rw-r--r--src/Configuration.h4
-rw-r--r--src/DuetNG/DuetEthernet/Network.cpp20
-rw-r--r--src/DuetNG/DuetEthernet/Network.h2
-rw-r--r--src/DuetNG/DuetEthernet/NetworkTransaction.cpp6
-rw-r--r--src/DuetNG/DuetEthernet/NetworkTransaction.h1
-rw-r--r--src/DuetNG/DuetEthernet/Socket.cpp126
-rw-r--r--src/DuetNG/DuetEthernet/Socket.h13
-rw-r--r--src/DuetNG/DuetEthernet/Wiznet/Ethernet/socketlib.cpp4
-rw-r--r--src/DuetNG/DuetEthernet/Wiznet/Internet/DHCP/dhcp.cpp2
-rw-r--r--src/DuetNG/DuetWiFi/Webserver.cpp12
-rw-r--r--src/Fan.cpp8
-rw-r--r--src/GCodes/GCodeMachineState.h8
-rw-r--r--src/GCodes/GCodes.cpp39
-rw-r--r--src/GCodes/GCodes.h70
-rw-r--r--src/GCodes/GCodes2.cpp6
-rw-r--r--src/Platform.cpp20
-rw-r--r--src/RepRapFirmware.h1
-rw-r--r--src/Version.h4
-rw-r--r--src/Webserver/Webserver.cpp96
-rw-r--r--src/Webserver/Webserver.h3
20 files changed, 268 insertions, 177 deletions
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(&currentStack, &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