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