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
diff options
context:
space:
mode:
authorDavid Crocker <dcrocker@eschertech.com>2017-03-28 20:55:22 +0300
committerDavid Crocker <dcrocker@eschertech.com>2017-03-28 21:35:35 +0300
commit66b7ee9ae2189e9ae09ce2c72327d570d551fe2a (patch)
tree5f5cd70f39b80004436b08f36566cc4f594982be /src/GCodes/GCodeInput.cpp
parentc95223c75d2946f6008a46f92f0d678106c1550c (diff)
Version 1.18RC1
Merged in chrishamm's code queue and input buffer code Increased heater tuning timeout for finding peak temperatire from 60 to 120 seconds Implemented M204 Increased precision of reported coordinates to 3 decimal places PanelDue status responses continue to be sent while executing M109/116/190/191 commands
Diffstat (limited to 'src/GCodes/GCodeInput.cpp')
-rw-r--r--src/GCodes/GCodeInput.cpp322
1 files changed, 322 insertions, 0 deletions
diff --git a/src/GCodes/GCodeInput.cpp b/src/GCodes/GCodeInput.cpp
new file mode 100644
index 00000000..ee97ec71
--- /dev/null
+++ b/src/GCodes/GCodeInput.cpp
@@ -0,0 +1,322 @@
+/*
+ * GCodeInput.cpp
+ *
+ * Created on: 16 Sep 2016
+ * Author: Christian
+ */
+
+#include "GCodeInput.h"
+
+#include "RepRap.h"
+#include "GCodes.h"
+
+
+// G-code input class for wrapping around Stream-based hardware ports
+
+void StreamGCodeInput::Reset()
+{
+ while (device.available() > 0)
+ {
+ device.read();
+ }
+}
+
+bool StreamGCodeInput::FillBuffer(GCodeBuffer *gb)
+{
+ size_t bytesToPass = min<size_t>(device.available(), GCODE_LENGTH);
+ for(size_t i = 0; i < bytesToPass; i++)
+ {
+ char c = static_cast<char>(device.read());
+
+ if (gb->WritingFileDirectory() == reprap.GetPlatform()->GetWebDir())
+ {
+ // HTML uploads are handled by the GCodes class
+ reprap.GetGCodes()->WriteHTMLToFile(*gb, c);
+ }
+ else if (gb->Put(c))
+ {
+ // Check if we can finish a file upload
+ if (gb->WritingFileDirectory() != nullptr)
+ {
+ reprap.GetGCodes()->WriteGCodeToFile(*gb);
+ gb->SetFinished(true);
+ }
+
+ // Code is complete, stop here
+ return true;
+ }
+ }
+
+ return false;
+}
+
+size_t StreamGCodeInput::BytesCached() const
+{
+ return device.available();
+}
+
+
+// Dynamic G-code input class for caching codes from software-defined sources
+
+
+RegularGCodeInput::RegularGCodeInput(bool removeComments): stripComments(removeComments),
+ state(GCodeInputState::idle), buffer(reinterpret_cast<char * const>(buf32)), writingPointer(0), readingPointer(0)
+{
+}
+
+void RegularGCodeInput::Reset()
+{
+ state = GCodeInputState::idle;
+ writingPointer = readingPointer = 0;
+}
+
+bool RegularGCodeInput::FillBuffer(GCodeBuffer *gb)
+{
+ size_t bytesToPass = min<size_t>(BytesCached(), GCODE_LENGTH);
+ for(size_t i = 0; i < bytesToPass; i++)
+ {
+ // Get a char from the buffer
+ char c = buffer[readingPointer++];
+ if (readingPointer == GCodeInputBufferSize)
+ {
+ readingPointer = 0;
+ }
+
+ // Pass it on to the GCodeBuffer
+ if (gb->WritingFileDirectory() == reprap.GetPlatform()->GetWebDir())
+ {
+ // HTML uploads are handled by the GCodes class
+ reprap.GetGCodes()->WriteHTMLToFile(*gb, c);
+ }
+ else if (gb->Put(c))
+ {
+ // Check if we can finish a file upload
+ if (gb->WritingFileDirectory() != nullptr)
+ {
+ reprap.GetGCodes()->WriteGCodeToFile(*gb);
+ gb->SetFinished(true);
+ }
+
+ // Code is complete, stop here
+ return true;
+ }
+ }
+
+ return false;
+}
+
+size_t RegularGCodeInput::BytesCached() const
+{
+ if (writingPointer >= readingPointer)
+ {
+ return writingPointer - readingPointer;
+ }
+ return GCodeInputBufferSize - readingPointer + writingPointer;
+}
+
+void RegularGCodeInput::Put(MessageType mtype, const char c)
+{
+ if (BufferSpaceLeft() == 0)
+ {
+ // Don't let the buffer overflow if we run out of space
+ return;
+ }
+
+ // Check for M112 (emergency stop) and for M122 (diagnostics) while receiving new characters
+ switch (state)
+ {
+ case GCodeInputState::idle:
+ if (c <= ' ')
+ {
+ // ignore whitespaces at the beginning
+ return;
+ }
+
+ state = (c == 'M') ? GCodeInputState::doingMCode : GCodeInputState::doingCode;
+ break;
+
+
+ case GCodeInputState::doingCode:
+ if (stripComments && c == ';')
+ {
+ // ignore comments if possible
+ state = GCodeInputState::inComment;
+ break;
+ }
+ // no break
+
+ case GCodeInputState::inComment:
+ if (c == 0 || c == '\r' || c == '\n')
+ {
+ state = GCodeInputState::idle;
+ }
+ break;
+
+ case GCodeInputState::doingMCode:
+ if (c == '1')
+ {
+ state = GCodeInputState::doingMCode1;
+ }
+ break;
+
+ case GCodeInputState::doingMCode1:
+ if (c == '1')
+ {
+ state = GCodeInputState::doingMCode11;
+ }
+ else if (c == '2')
+ {
+ state = GCodeInputState::doingMCode12;
+ }
+ else
+ {
+ state = GCodeInputState::doingCode;
+ }
+ break;
+
+ case GCodeInputState::doingMCode11:
+ if (c == '2')
+ {
+ state = GCodeInputState::doingMCode112;
+ break;
+ }
+ state = GCodeInputState::doingCode;
+ break;
+
+ case GCodeInputState::doingMCode12:
+ if (c == '2')
+ {
+ state = GCodeInputState::doingMCode122;
+ break;
+ }
+ state = GCodeInputState::doingCode;
+ break;
+
+ case GCodeInputState::doingMCode112:
+ if (c <= ' ' || c == ';')
+ {
+ // Emergency stop requested - perform it now
+ reprap.EmergencyStop();
+ reprap.GetGCodes()->Reset();
+
+ // But don't run it twice
+ Reset();
+ return;
+ }
+
+ state = GCodeInputState::doingCode;
+ break;
+
+ case GCodeInputState::doingMCode122:
+ if (c <= ' ' || c == ';')
+ {
+ // Diagnostics requested - report them now
+ // Only send the report to the appropriate channel, because if we send it as a generic message instead then it gets truncated.
+ reprap.Diagnostics(mtype);
+
+ // But don't report them twice
+ Reset();
+ return;
+ }
+ break;
+ }
+
+ // Feed another character into the buffer
+ if (state != GCodeInputState::inComment)
+ {
+ buffer[writingPointer++] = c;
+ if (writingPointer == GCodeInputBufferSize)
+ {
+ writingPointer = 0;
+ }
+ }
+}
+
+void RegularGCodeInput::Put(MessageType mtype, const char *buf)
+{
+ Put(mtype, buf, strlen(buf) + 1);
+}
+
+void RegularGCodeInput::Put(MessageType mtype, const char *buf, size_t len)
+{
+ if (len > BufferSpaceLeft())
+ {
+ // Don't cache this if we don't have enough space left
+ return;
+ }
+
+ for (size_t i = 0; i < len; i++)
+ {
+ Put(mtype, buf[i]);
+ }
+}
+
+size_t RegularGCodeInput::BufferSpaceLeft() const
+{
+ return (readingPointer - writingPointer - 1u) % GCodeInputBufferSize;
+}
+
+
+// File-based G-code input source
+
+// Reset this input. Should be called when the associated file is being closed
+void FileGCodeInput::Reset()
+{
+ lastFile = nullptr;
+ RegularGCodeInput::Reset();
+}
+
+// Read another chunk of G-codes from the file and return true if more data is available
+bool FileGCodeInput::ReadFromFile(FileData &file)
+{
+ const size_t bytesCached = BytesCached();
+
+ // Keep track of the last file we read from
+ if (lastFile != nullptr && lastFile != file.f)
+ {
+ if (bytesCached > 0)
+ {
+ // Rewind back to the right position so we can resume at the right position later.
+ // This may be necessary when nested macros are executed.
+ lastFile->Seek(lastFile->Position() - bytesCached);
+ }
+
+ RegularGCodeInput::Reset();
+ }
+ lastFile = file.f;
+
+ // Read more from the file
+ if (bytesCached < GCodeInputFileReadThreshold)
+ {
+ // Reset the read+write pointers for better performance if possible
+ if (readingPointer == writingPointer)
+ {
+ readingPointer = writingPointer = 0;
+ }
+
+ // Read blocks with sizes multiple of 4 for HSMCI efficiency
+ uint32_t readBuffer32[(GCodeInputBufferSize + 3) / 4];
+ char * const readBuffer = reinterpret_cast<char * const>(readBuffer32);
+
+ int bytesRead = file.Read(readBuffer, BufferSpaceLeft() & (~3));
+ if (bytesRead > 0)
+ {
+ int remaining = GCodeInputBufferSize - writingPointer;
+ if (bytesRead <= remaining)
+ {
+ memcpy(buffer + writingPointer, readBuffer, bytesRead);
+ }
+ else
+ {
+ memcpy(buffer + writingPointer, readBuffer, remaining);
+ memcpy(buffer, readBuffer + remaining, bytesRead - remaining);
+ }
+ writingPointer = (writingPointer + bytesRead) % GCodeInputBufferSize;
+
+ return true;
+ }
+ }
+
+ return bytesCached > 0;
+}
+