diff --git a/Marlin/frameworks/CMSIS/LPC1768/lib/Print.cpp b/Marlin/frameworks/CMSIS/LPC1768/lib/Print.cpp
index d5ea7c7f4b..9219d0515b 100644
--- a/Marlin/frameworks/CMSIS/LPC1768/lib/Print.cpp
+++ b/Marlin/frameworks/CMSIS/LPC1768/lib/Print.cpp
@@ -28,7 +28,10 @@
 #include "Print.h"
 #include <stdarg.h>
 
-#define PrintfEnable  0
+#define PrintfEnable  1
+typedef signed short sint16_t;
+typedef signed long sint32_t;
+
 // Public Methods //////////////////////////////////////////////////////////////
 
 /* default implementation: may be overridden */
diff --git a/Marlin/frameworks/CMSIS/LPC1768/lib/Stream.cpp b/Marlin/frameworks/CMSIS/LPC1768/lib/Stream.cpp
new file mode 100644
index 0000000000..b1e507e9e8
--- /dev/null
+++ b/Marlin/frameworks/CMSIS/LPC1768/lib/Stream.cpp
@@ -0,0 +1,319 @@
+/*
+ Stream.cpp - adds parsing methods to Stream class
+ Copyright (c) 2008 David A. Mellis.  All right reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+ Created July 2011
+ parsing functions based on TextFinder library by Michael Margolis
+
+ findMulti/findUntil routines written by Jim Leonard/Xuth
+ */
+
+#include <stdlib.h>
+#include "../../../../src/HAL/HAL_LPC1768/arduino.h"
+
+#include "Stream.h"
+
+#define PARSE_TIMEOUT 1000  // default number of milli-seconds to wait
+#define NO_SKIP_CHAR  1  // a magic char not found in a valid ASCII numeric field
+
+// private method to read stream with timeout
+int Stream::timedRead()
+{
+  int c;
+  _startMillis = millis();
+  do {
+    c = read();
+    if (c >= 0) return c;
+  } while(millis() - _startMillis < _timeout);
+  return -1;     // -1 indicates timeout
+}
+
+// private method to peek stream with timeout
+int Stream::timedPeek()
+{
+  int c;
+  _startMillis = millis();
+  do {
+    c = peek();
+    if (c >= 0) return c;
+  } while(millis() - _startMillis < _timeout);
+  return -1;     // -1 indicates timeout
+}
+
+// returns peek of the next digit in the stream or -1 if timeout
+// discards non-numeric characters
+int Stream::peekNextDigit()
+{
+  int c;
+  while (1) {
+    c = timedPeek();
+    if (c < 0) return c;  // timeout
+    if (c == '-') return c;
+    if (c >= '0' && c <= '9') return c;
+    read();  // discard non-numeric
+  }
+}
+
+// Public Methods
+//////////////////////////////////////////////////////////////
+
+void Stream::setTimeout(unsigned long timeout)  // sets the maximum number of milliseconds to wait
+{
+  _timeout = timeout;
+}
+
+ // find returns true if the target string is found
+bool  Stream::find(char *target)
+{
+  return findUntil(target, strlen(target), NULL, 0);
+}
+
+// reads data from the stream until the target string of given length is found
+// returns true if target string is found, false if timed out
+bool Stream::find(char *target, size_t length)
+{
+  return findUntil(target, length, NULL, 0);
+}
+
+// as find but search ends if the terminator string is found
+bool  Stream::findUntil(char *target, char *terminator)
+{
+  return findUntil(target, strlen(target), terminator, strlen(terminator));
+}
+
+// reads data from the stream until the target string of the given length is found
+// search terminated if the terminator string is found
+// returns true if target string is found, false if terminated or timed out
+bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen)
+{
+  if (terminator == NULL) {
+    MultiTarget t[1] = {{target, targetLen, 0}};
+    return findMulti(t, 1) == 0 ? true : false;
+  } else {
+    MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}};
+    return findMulti(t, 2) == 0 ? true : false;
+  }
+}
+
+
+// returns the first valid (long) integer value from the current position.
+// initial characters that are not digits (or the minus sign) are skipped
+// function is terminated by the first character that is not a digit.
+long Stream::parseInt()
+{
+  return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
+}
+
+// as above but a given skipChar is ignored
+// this allows format characters (typically commas) in values to be ignored
+long Stream::parseInt(char skipChar)
+{
+  bool isNegative = false;
+  long value = 0;
+  int c;
+
+  c = peekNextDigit();
+  // ignore non numeric leading characters
+  if(c < 0)
+    return 0; // zero returned if timeout
+
+  do{
+    if(c == skipChar)
+      ; // ignore this charactor
+    else if(c == '-')
+      isNegative = true;
+    else if(c >= '0' && c <= '9')        // is c a digit?
+      value = value * 10 + c - '0';
+    read();  // consume the character we got with peek
+    c = timedPeek();
+  }
+  while( (c >= '0' && c <= '9') || c == skipChar );
+
+  if(isNegative)
+    value = -value;
+  return value;
+}
+
+
+// as parseInt but returns a floating point value
+float Stream::parseFloat()
+{
+  return parseFloat(NO_SKIP_CHAR);
+}
+
+// as above but the given skipChar is ignored
+// this allows format characters (typically commas) in values to be ignored
+float Stream::parseFloat(char skipChar){
+  bool isNegative = false;
+  bool isFraction = false;
+  long value = 0;
+  char c;
+  float fraction = 1.0;
+
+  c = peekNextDigit();
+    // ignore non numeric leading characters
+  if(c < 0)
+    return 0; // zero returned if timeout
+
+  do{
+    if(c == skipChar)
+      ; // ignore
+    else if(c == '-')
+      isNegative = true;
+    else if (c == '.')
+      isFraction = true;
+    else if(c >= '0' && c <= '9')  {      // is c a digit?
+      value = value * 10 + c - '0';
+      if(isFraction)
+         fraction *= 0.1;
+    }
+    read();  // consume the character we got with peek
+    c = timedPeek();
+  }
+  while( (c >= '0' && c <= '9')  || c == '.' || c == skipChar );
+
+  if(isNegative)
+    value = -value;
+  if(isFraction)
+    return value * fraction;
+  else
+    return value;
+}
+
+// read characters from stream into buffer
+// terminates if length characters have been read, or timeout (see setTimeout)
+// returns the number of characters placed in the buffer
+// the buffer is NOT null terminated.
+//
+size_t Stream::readBytes(char *buffer, size_t length)
+{
+  size_t count = 0;
+  while (count < length) {
+    int c = timedRead();
+    if (c < 0) break;
+    *buffer++ = (char)c;
+    count++;
+  }
+  return count;
+}
+
+
+// as readBytes with terminator character
+// terminates if length characters have been read, timeout, or if the terminator character  detected
+// returns the number of characters placed in the buffer (0 means no valid data found)
+
+size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
+{
+  if (length < 1) return 0;
+  size_t index = 0;
+  while (index < length) {
+    int c = timedRead();
+    if (c < 0 || c == terminator) break;
+    *buffer++ = (char)c;
+    index++;
+  }
+  return index; // return number of characters, not including null terminator
+}
+
+String Stream::readString()
+{
+  String ret;
+  int c = timedRead();
+  while (c >= 0)
+  {
+    ret += (char)c;
+    c = timedRead();
+  }
+  return ret;
+}
+
+String Stream::readStringUntil(char terminator)
+{
+  String ret;
+  int c = timedRead();
+  while (c >= 0 && c != terminator)
+  {
+    ret += (char)c;
+    c = timedRead();
+  }
+  return ret;
+}
+
+int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) {
+  // any zero length target string automatically matches and would make
+  // a mess of the rest of the algorithm.
+  for (struct MultiTarget *t = targets; t < targets+tCount; ++t) {
+    if (t->len <= 0)
+      return t - targets;
+  }
+
+  while (1) {
+    int c = timedRead();
+    if (c < 0)
+      return -1;
+
+    for (struct MultiTarget *t = targets; t < targets+tCount; ++t) {
+      // the simple case is if we match, deal with that first.
+      if (c == t->str[t->index]) {
+        if (++t->index == t->len)
+          return t - targets;
+        else
+          continue;
+      }
+
+      // if not we need to walk back and see if we could have matched further
+      // down the stream (ie '1112' doesn't match the first position in '11112'
+      // but it will match the second position so we can't just reset the current
+      // index to 0 when we find a mismatch.
+      if (t->index == 0)
+        continue;
+
+      int origIndex = t->index;
+      do {
+        --t->index;
+        // first check if current char works against the new current index
+        if (c != t->str[t->index])
+          continue;
+
+        // if it's the only char then we're good, nothing more to check
+        if (t->index == 0) {
+          t->index++;
+          break;
+        }
+
+        // otherwise we need to check the rest of the found string
+        int diff = origIndex - t->index;
+        size_t i;
+        for (i = 0; i < t->index; ++i) {
+          if (t->str[i] != t->str[i + diff])
+            break;
+        }
+
+        // if we successfully got through the previous loop then our current
+        // index is good.
+        if (i == t->index) {
+          t->index++;
+          break;
+        }
+
+        // otherwise we just try the next index
+      } while (t->index);
+    }
+  }
+  // unreachable
+  return -1;
+}
diff --git a/Marlin/frameworks/CMSIS/LPC1768/lib/Stream.h b/Marlin/frameworks/CMSIS/LPC1768/lib/Stream.h
new file mode 100644
index 0000000000..a0be7a9e60
--- /dev/null
+++ b/Marlin/frameworks/CMSIS/LPC1768/lib/Stream.h
@@ -0,0 +1,117 @@
+/*
+  Stream.h - base class for character-based streams.
+  Copyright (c) 2010 David A. Mellis.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+  parsing functions based on TextFinder library by Michael Margolis
+*/
+
+#ifndef Stream_h
+#define Stream_h
+
+#include <stdint.h>
+#include <inttypes.h>
+#include "Print.h"
+#include "WString.h"
+
+// compatability macros for testing
+/*
+#define   getInt()            parseInt()
+#define   getInt(skipChar)    parseInt(skipchar)
+#define   getFloat()          parseFloat()
+#define   getFloat(skipChar)  parseFloat(skipChar)
+#define   getString( pre_string, post_string, buffer, length)
+readBytesBetween( pre_string, terminator, buffer, length)
+*/
+
+class Stream : public Print
+{
+  protected:
+    unsigned long _timeout;      // number of milliseconds to wait for the next char before aborting timed read
+    unsigned long _startMillis;  // used for timeout measurement
+    int timedRead();    // private method to read stream with timeout
+    int timedPeek();    // private method to peek stream with timeout
+    int peekNextDigit(); // returns the next numeric digit in the stream or -1 if timeout
+
+  public:
+    virtual int available() = 0;
+    virtual int read() = 0;
+    virtual int peek() = 0;
+    virtual void flush() = 0;
+
+    Stream() {_timeout=1000;}
+
+// parsing methods
+
+  void setTimeout(unsigned long timeout);  // sets maximum milliseconds to wait for stream data, default is 1 second
+
+  bool find(char *target);   // reads data from the stream until the target string is found
+  bool find(uint8_t *target) { return find ((char *)target); }
+  // returns true if target string is found, false if timed out (see setTimeout)
+
+  bool find(char *target, size_t length);   // reads data from the stream until the target string of given length is found
+  bool find(uint8_t *target, size_t length) { return find ((char *)target, length); }
+  // returns true if target string is found, false if timed out
+
+  bool find(char target) { return find (&target, 1); }
+
+  bool findUntil(char *target, char *terminator);   // as find but search ends if the terminator string is found
+  bool findUntil(uint8_t *target, char *terminator) { return findUntil((char *)target, terminator); }
+
+  bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen);   // as above but search ends if the terminate string is found
+  bool findUntil(uint8_t *target, size_t targetLen, char *terminate, size_t termLen) {return findUntil((char *)target, targetLen, terminate, termLen); }
+
+
+  long parseInt(); // returns the first valid (long) integer value from the current position.
+  // initial characters that are not digits (or the minus sign) are skipped
+  // integer is terminated by the first character that is not a digit.
+
+  float parseFloat();               // float version of parseInt
+
+  size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer
+  size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); }
+  // terminates if length characters have been read or timeout (see setTimeout)
+  // returns the number of characters placed in the buffer (0 means no valid data found)
+
+  size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character
+  size_t readBytesUntil( char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, (char *)buffer, length); }
+  // terminates if length characters have been read, timeout, or if the terminator character  detected
+  // returns the number of characters placed in the buffer (0 means no valid data found)
+
+  // Arduino String functions to be added here
+  String readString();
+  String readStringUntil(char terminator);
+
+  protected:
+  long parseInt(char skipChar); // as above but the given skipChar is ignored
+  // as above but the given skipChar is ignored
+  // this allows format characters (typically commas) in values to be ignored
+
+  float parseFloat(char skipChar);  // as above but the given skipChar is ignored
+
+  struct MultiTarget {
+    const char *str;  // string you're searching for
+    size_t len;       // length of string you're searching for
+    size_t index;     // index used by the search routine.
+  };
+
+  // This allows you to search for an arbitrary number of strings.
+  // Returns index of the target that is found first or -1 if timeout occurs.
+  int findMulti(struct MultiTarget *targets, int tCount);
+};
+
+
+#endif
diff --git a/Marlin/frameworks/CMSIS/LPC1768/lib/WString.h b/Marlin/frameworks/CMSIS/LPC1768/lib/WString.h
new file mode 100644
index 0000000000..8a1876424b
--- /dev/null
+++ b/Marlin/frameworks/CMSIS/LPC1768/lib/WString.h
@@ -0,0 +1,229 @@
+/*
+  WString.h - String library for Wiring & Arduino
+  ...mostly rewritten by Paul Stoffregen...
+  Copyright (c) 2009-10 Hernando Barragan.  All right reserved.
+  Copyright 2011, Paul Stoffregen, paul@pjrc.com
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef String_class_h
+#define String_class_h
+#ifdef __cplusplus
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+//#include <avr/pgmspace.h>
+
+// When compiling programs with this class, the following gcc parameters
+// dramatically increase performance and memory (RAM) efficiency, typically
+// with little or no increase in code size.
+//     -felide-constructors
+//     -std=c++0x
+
+class __FlashStringHelper;
+#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
+
+// An inherited class for holding the result of a concatenation.  These
+// result objects are assumed to be writable by subsequent concatenations.
+class StringSumHelper;
+
+// The string class
+class String
+{
+	// use a function pointer to allow for "if (s)" without the
+	// complications of an operator bool(). for more information, see:
+	// http://www.artima.com/cppsource/safebool.html
+	typedef void (String::*StringIfHelperType)() const;
+	void StringIfHelper() const {}
+
+public:
+	// constructors
+	// creates a copy of the initial value.
+	// if the initial value is null or invalid, or if memory allocation
+	// fails, the string will be marked as invalid (i.e. "if (s)" will
+	// be false).
+	String(const char *cstr = "");
+	String(const String &str);
+	String(const __FlashStringHelper *str);
+       #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
+	String(String &&rval);
+	String(StringSumHelper &&rval);
+	#endif
+	explicit String(char c);
+	explicit String(unsigned char, unsigned char base=10);
+	explicit String(int, unsigned char base=10);
+	explicit String(unsigned int, unsigned char base=10);
+	explicit String(long, unsigned char base=10);
+	explicit String(unsigned long, unsigned char base=10);
+	explicit String(float, unsigned char decimalPlaces=2);
+	explicit String(double, unsigned char decimalPlaces=2);
+	~String(void);
+
+	// memory management
+	// return true on success, false on failure (in which case, the string
+	// is left unchanged).  reserve(0), if successful, will validate an
+	// invalid string (i.e., "if (s)" will be true afterwards)
+	unsigned char reserve(unsigned int size);
+	inline unsigned int length(void) const {return len;}
+
+	// creates a copy of the assigned value.  if the value is null or
+	// invalid, or if the memory allocation fails, the string will be
+	// marked as invalid ("if (s)" will be false).
+	String & operator = (const String &rhs);
+	String & operator = (const char *cstr);
+	String & operator = (const __FlashStringHelper *str);
+       #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
+	String & operator = (String &&rval);
+	String & operator = (StringSumHelper &&rval);
+	#endif
+
+	// concatenate (works w/ built-in types)
+
+	// returns true on success, false on failure (in which case, the string
+	// is left unchanged).  if the argument is null or invalid, the
+	// concatenation is considered unsucessful.
+	unsigned char concat(const String &str);
+	unsigned char concat(const char *cstr);
+	unsigned char concat(char c);
+	unsigned char concat(unsigned char c);
+	unsigned char concat(int num);
+	unsigned char concat(unsigned int num);
+	unsigned char concat(long num);
+	unsigned char concat(unsigned long num);
+	unsigned char concat(float num);
+	unsigned char concat(double num);
+	unsigned char concat(const __FlashStringHelper * str);
+
+	// if there's not enough memory for the concatenated value, the string
+	// will be left unchanged (but this isn't signalled in any way)
+	String & operator += (const String &rhs)	{concat(rhs); return (*this);}
+	String & operator += (const char *cstr)		{concat(cstr); return (*this);}
+	String & operator += (char c)			{concat(c); return (*this);}
+	String & operator += (unsigned char num)		{concat(num); return (*this);}
+	String & operator += (int num)			{concat(num); return (*this);}
+	String & operator += (unsigned int num)		{concat(num); return (*this);}
+	String & operator += (long num)			{concat(num); return (*this);}
+	String & operator += (unsigned long num)	{concat(num); return (*this);}
+	String & operator += (float num)		{concat(num); return (*this);}
+	String & operator += (double num)		{concat(num); return (*this);}
+	String & operator += (const __FlashStringHelper *str){concat(str); return (*this);}
+
+	friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs);
+	friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr);
+	friend StringSumHelper & operator + (const StringSumHelper &lhs, char c);
+	friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num);
+	friend StringSumHelper & operator + (const StringSumHelper &lhs, int num);
+	friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num);
+	friend StringSumHelper & operator + (const StringSumHelper &lhs, long num);
+	friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num);
+	friend StringSumHelper & operator + (const StringSumHelper &lhs, float num);
+	friend StringSumHelper & operator + (const StringSumHelper &lhs, double num);
+	friend StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs);
+
+	// comparison (only works w/ Strings and "strings")
+	operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; }
+	int compareTo(const String &s) const;
+	unsigned char equals(const String &s) const;
+	unsigned char equals(const char *cstr) const;
+	unsigned char operator == (const String &rhs) const {return equals(rhs);}
+	unsigned char operator == (const char *cstr) const {return equals(cstr);}
+	unsigned char operator != (const String &rhs) const {return !equals(rhs);}
+	unsigned char operator != (const char *cstr) const {return !equals(cstr);}
+	unsigned char operator <  (const String &rhs) const;
+	unsigned char operator >  (const String &rhs) const;
+	unsigned char operator <= (const String &rhs) const;
+	unsigned char operator >= (const String &rhs) const;
+	unsigned char equalsIgnoreCase(const String &s) const;
+	unsigned char startsWith( const String &prefix) const;
+	unsigned char startsWith(const String &prefix, unsigned int offset) const;
+	unsigned char endsWith(const String &suffix) const;
+
+	// character acccess
+	char charAt(unsigned int index) const;
+	void setCharAt(unsigned int index, char c);
+	char operator [] (unsigned int index) const;
+	char& operator [] (unsigned int index);
+	void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const;
+	void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const
+		{ getBytes((unsigned char *)buf, bufsize, index); }
+	const char* c_str() const { return buffer; }
+	char* begin() { return buffer; }
+	char* end() { return buffer + length(); }
+	const char* begin() const { return c_str(); }
+	const char* end() const { return c_str() + length(); }
+
+	// search
+	int indexOf( char ch ) const;
+	int indexOf( char ch, unsigned int fromIndex ) const;
+	int indexOf( const String &str ) const;
+	int indexOf( const String &str, unsigned int fromIndex ) const;
+	int lastIndexOf( char ch ) const;
+	int lastIndexOf( char ch, unsigned int fromIndex ) const;
+	int lastIndexOf( const String &str ) const;
+	int lastIndexOf( const String &str, unsigned int fromIndex ) const;
+	String substring( unsigned int beginIndex ) const { return substring(beginIndex, len); };
+	String substring( unsigned int beginIndex, unsigned int endIndex ) const;
+
+	// modification
+	void replace(char find, char replace);
+	void replace(const String& find, const String& replace);
+	void remove(unsigned int index);
+	void remove(unsigned int index, unsigned int count);
+	void toLowerCase(void);
+	void toUpperCase(void);
+	void trim(void);
+
+	// parsing/conversion
+	long toInt(void) const;
+	float toFloat(void) const;
+	double toDouble(void) const;
+
+protected:
+	char *buffer;	        // the actual char array
+	unsigned int capacity;  // the array length minus one (for the '\0')
+	unsigned int len;       // the String length (not counting the '\0')
+protected:
+	void init(void);
+	void invalidate(void);
+	unsigned char changeBuffer(unsigned int maxStrLen);
+	unsigned char concat(const char *cstr, unsigned int length);
+
+	// copy and move
+	String & copy(const char *cstr, unsigned int length);
+	String & copy(const __FlashStringHelper *pstr, unsigned int length);
+       #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
+	void move(String &rhs);
+	#endif
+};
+
+class StringSumHelper : public String
+{
+public:
+	StringSumHelper(const String &s) : String(s) {}
+	StringSumHelper(const char *p) : String(p) {}
+	StringSumHelper(char c) : String(c) {}
+	StringSumHelper(unsigned char num) : String(num) {}
+	StringSumHelper(int num) : String(num) {}
+	StringSumHelper(unsigned int num) : String(num) {}
+	StringSumHelper(long num) : String(num) {}
+	StringSumHelper(unsigned long num) : String(num) {}
+	StringSumHelper(float num) : String(num) {}
+	StringSumHelper(double num) : String(num) {}
+};
+
+#endif  // __cplusplus
+#endif  // String_class_h
diff --git a/Marlin/src/HAL/HAL_LPC1768/HardwareSerial.cpp b/Marlin/src/HAL/HAL_LPC1768/HardwareSerial.cpp
new file mode 100644
index 0000000000..b195fab1ca
--- /dev/null
+++ b/Marlin/src/HAL/HAL_LPC1768/HardwareSerial.cpp
@@ -0,0 +1,636 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "../../../macros.h"
+#include "../HAL.h"
+#include "HardwareSerial.h"
+#define UART3 3
+HardwareSerial Serial3 = HardwareSerial(UART3);
+
+volatile uint32_t UART0Status, UART1Status, UART2Status, UART3Status;
+volatile uint8_t UART0TxEmpty = 1, UART1TxEmpty = 1, UART2TxEmpty=1, UART3TxEmpty=1;
+volatile uint8_t UART0Buffer[UARTRXQUEUESIZE], UART1Buffer[UARTRXQUEUESIZE], UART2Buffer[UARTRXQUEUESIZE], UART3Buffer[UARTRXQUEUESIZE];
+volatile uint32_t UART0RxQueueWritePos = 0, UART1RxQueueWritePos = 0, UART2RxQueueWritePos = 0, UART3RxQueueWritePos = 0;
+volatile uint32_t UART0RxQueueReadPos = 0, UART1RxQueueReadPos = 0, UART2RxQueueReadPos = 0, UART3RxQueueReadPos = 0;
+volatile uint8_t dummy;
+
+  void HardwareSerial::begin(uint32_t baudrate) {
+    uint32_t Fdiv;
+     uint32_t pclkdiv, pclk;
+
+     if ( PortNum == 0 )
+     {
+   	LPC_PINCON->PINSEL0 &= ~0x000000F0;
+   	LPC_PINCON->PINSEL0 |= 0x00000050;  /* RxD0 is P0.3 and TxD0 is P0.2 */
+   	/* By default, the PCLKSELx value is zero, thus, the PCLK for
+   	all the peripherals is 1/4 of the SystemFrequency. */
+   	/* Bit 6~7 is for UART0 */
+   	pclkdiv = (LPC_SC->PCLKSEL0 >> 6) & 0x03;
+   	switch ( pclkdiv )
+   	{
+   	  case 0x00:
+   	  default:
+   		pclk = SystemCoreClock/4;
+   		break;
+   	  case 0x01:
+   		pclk = SystemCoreClock;
+   		break;
+   	  case 0x02:
+   		pclk = SystemCoreClock/2;
+   		break;
+   	  case 0x03:
+   		pclk = SystemCoreClock/8;
+   		break;
+   	}
+
+       LPC_UART0->LCR = 0x83;		/* 8 bits, no Parity, 1 Stop bit */
+   	Fdiv = ( pclk / 16 ) / baudrate ;	/*baud rate */
+       LPC_UART0->DLM = Fdiv / 256;
+       LPC_UART0->DLL = Fdiv % 256;
+   	LPC_UART0->LCR = 0x03;		/* DLAB = 0 */
+       LPC_UART0->FCR = 0x07;		/* Enable and reset TX and RX FIFO. */
+
+      	NVIC_EnableIRQ(UART0_IRQn);
+
+       LPC_UART0->IER = IER_RBR | IER_THRE | IER_RLS;	/* Enable UART0 interrupt */
+     }
+     else if ( PortNum == 1 )
+     {
+   	LPC_PINCON->PINSEL4 &= ~0x0000000F;
+   	LPC_PINCON->PINSEL4 |= 0x0000000A;	/* Enable RxD1 P2.1, TxD1 P2.0 */
+
+   	/* By default, the PCLKSELx value is zero, thus, the PCLK for
+   	all the peripherals is 1/4 of the SystemFrequency. */
+   	/* Bit 8,9 are for UART1 */
+   	pclkdiv = (LPC_SC->PCLKSEL0 >> 8) & 0x03;
+   	switch ( pclkdiv )
+   	{
+   	  case 0x00:
+   	  default:
+   		pclk = SystemCoreClock/4;
+   		break;
+   	  case 0x01:
+   		pclk = SystemCoreClock;
+   		break;
+   	  case 0x02:
+   		pclk = SystemCoreClock/2;
+   		break;
+   	  case 0x03:
+   		pclk = SystemCoreClock/8;
+   		break;
+   	}
+
+       LPC_UART1->LCR = 0x83;		/* 8 bits, no Parity, 1 Stop bit */
+   	Fdiv = ( pclk / 16 ) / baudrate ;	/*baud rate */
+       LPC_UART1->DLM = Fdiv / 256;
+       LPC_UART1->DLL = Fdiv % 256;
+   	LPC_UART1->LCR = 0x03;		/* DLAB = 0 */
+       LPC_UART1->FCR = 0x07;		/* Enable and reset TX and RX FIFO. */
+
+      	NVIC_EnableIRQ(UART1_IRQn);
+
+       LPC_UART1->IER = IER_RBR | IER_THRE | IER_RLS;	/* Enable UART1 interrupt */
+     }
+     else if ( PortNum == 2 )
+     {
+   	  //LPC_PINCON->PINSEL4 &= ~0x000F0000;  /*Pinsel4 Bits 16-19*/
+   	  //LPC_PINCON->PINSEL4 |=  0x000A0000;  /* RxD2 is P2.9 and TxD2 is P2.8, value 10*/
+   	  LPC_PINCON->PINSEL0 &= ~0x00F00000;  /*Pinsel0 Bits 20-23*/
+   	  LPC_PINCON->PINSEL0 |=  0x00500000;  /* RxD2 is P0.11 and TxD2 is P0.10, value 01*/
+
+   	  LPC_SC->PCONP |= 1<<24; //Enable PCUART2
+   	  /* By default, the PCLKSELx value is zero, thus, the PCLK for
+   		all the peripherals is 1/4 of the SystemFrequency. */
+   	  /* Bit 6~7 is for UART3 */
+   	  pclkdiv = (LPC_SC->PCLKSEL1 >> 16) & 0x03;
+   	  switch ( pclkdiv )
+   	  {
+   	  case 0x00:
+   	  default:
+   		  pclk = SystemCoreClock/4;
+   		  break;
+   	  case 0x01:
+   		  pclk = SystemCoreClock;
+   		  break;
+   	  case 0x02:
+   		  pclk = SystemCoreClock/2;
+   		  break;
+   	  case 0x03:
+   		  pclk = SystemCoreClock/8;
+   		  break;
+   	  }
+   	  LPC_UART2->LCR = 0x83;		/* 8 bits, no Parity, 1 Stop bit */
+   	  Fdiv = ( pclk / 16 ) / baudrate ;	/*baud rate */
+   	  LPC_UART2->DLM = Fdiv / 256;
+   	  LPC_UART2->DLL = Fdiv % 256;
+   	  LPC_UART2->LCR = 0x03;		/* DLAB = 0 */
+   	  LPC_UART2->FCR = 0x07;		/* Enable and reset TX and RX FIFO. */
+
+   	  NVIC_EnableIRQ(UART2_IRQn);
+
+   	  LPC_UART2->IER = IER_RBR | IER_THRE | IER_RLS;	/* Enable UART3 interrupt */
+     }
+     else if ( PortNum == 3 )
+     {
+   	  LPC_PINCON->PINSEL0 &= ~0x0000000F;
+   	  LPC_PINCON->PINSEL0 |=  0x0000000A;  /* RxD3 is P0.1 and TxD3 is P0.0 */
+   	  LPC_SC->PCONP |= 1<<4 | 1<<25; //Enable PCUART1
+   	  /* By default, the PCLKSELx value is zero, thus, the PCLK for
+   		all the peripherals is 1/4 of the SystemFrequency. */
+   	  /* Bit 6~7 is for UART3 */
+   	  pclkdiv = (LPC_SC->PCLKSEL1 >> 18) & 0x03;
+   	  switch ( pclkdiv )
+   	  {
+   	  case 0x00:
+   	  default:
+   		  pclk = SystemCoreClock/4;
+   		  break;
+   	  case 0x01:
+   		  pclk = SystemCoreClock;
+   		  break;
+   	  case 0x02:
+   		  pclk = SystemCoreClock/2;
+   		  break;
+   	  case 0x03:
+   		  pclk = SystemCoreClock/8;
+   		  break;
+   	  }
+   	  LPC_UART3->LCR = 0x83;		/* 8 bits, no Parity, 1 Stop bit */
+   	  Fdiv = ( pclk / 16 ) / baudrate ;	/*baud rate */
+   	  LPC_UART3->DLM = Fdiv / 256;
+   	  LPC_UART3->DLL = Fdiv % 256;
+   	  LPC_UART3->LCR = 0x03;		/* DLAB = 0 */
+   	  LPC_UART3->FCR = 0x07;		/* Enable and reset TX and RX FIFO. */
+
+   	  NVIC_EnableIRQ(UART3_IRQn);
+
+   	  LPC_UART3->IER = IER_RBR | IER_THRE | IER_RLS;	/* Enable UART3 interrupt */
+     }
+  }
+
+  int HardwareSerial::read() {
+    uint8_t rx;
+  	if ( PortNum == 0 )
+  	  {
+  		  if (UART0RxQueueReadPos == UART0RxQueueWritePos)
+  		    return -1;
+
+  		  // Read from "head"
+  		  rx = UART0Buffer[UART0RxQueueReadPos]; // grab next byte
+  		  UART0RxQueueReadPos = (UART0RxQueueReadPos + 1) % UARTRXQUEUESIZE;
+  		  return rx;
+  	  }
+  	  if ( PortNum == 1 )
+  	  {
+  		  if (UART1RxQueueReadPos == UART1RxQueueWritePos)
+  		    return -1;
+
+  		  // Read from "head"
+  		  rx = UART1Buffer[UART1RxQueueReadPos]; // grab next byte
+  		  UART1RxQueueReadPos = (UART1RxQueueReadPos + 1) % UARTRXQUEUESIZE;
+  		  return rx;
+  	  }
+  	  if ( PortNum == 2 )
+  	  {
+  		  if (UART2RxQueueReadPos == UART2RxQueueWritePos)
+  		    return -1;
+
+  		  // Read from "head"
+  		  rx = UART2Buffer[UART2RxQueueReadPos]; // grab next byte
+  		  UART2RxQueueReadPos = (UART2RxQueueReadPos + 1) % UARTRXQUEUESIZE;
+  		  return rx;
+  	  }
+  	  if ( PortNum == 3 )
+  	  {
+  		  if (UART3RxQueueReadPos == UART3RxQueueWritePos)
+  		    return -1;
+
+  		  // Read from "head"
+  		  rx = UART3Buffer[UART3RxQueueReadPos]; // grab next byte
+  		  UART3RxQueueReadPos = (UART3RxQueueReadPos + 1) % UARTRXQUEUESIZE;
+  		  return rx;
+  	  }
+  	  return 0;
+  }
+
+  size_t HardwareSerial::write(uint8_t send) {
+    if ( PortNum == 0 )
+     {
+   	  /* THRE status, contain valid data */
+   	  while ( !(UART0TxEmpty & 0x01) );
+   	  LPC_UART0->THR = send;
+   	  UART0TxEmpty = 0;	/* not empty in the THR until it shifts out */
+     }
+     else if (PortNum == 1)
+     {
+
+   	  /* THRE status, contain valid data */
+   	  while ( !(UART1TxEmpty & 0x01) );
+   	  LPC_UART1->THR = send;
+   	  UART1TxEmpty = 0;	/* not empty in the THR until it shifts out */
+
+
+     }
+     else if ( PortNum == 2 )
+     {
+   	  /* THRE status, contain valid data */
+   	  while ( !(UART2TxEmpty & 0x01) );
+   	  LPC_UART2->THR = send;
+   	  UART2TxEmpty = 0;	/* not empty in the THR until it shifts out */
+
+     }
+     else if ( PortNum == 3 )
+     {
+   	  /* THRE status, contain valid data */
+   	  while ( !(UART3TxEmpty & 0x01) );
+   	  LPC_UART3->THR = send;
+   	  UART3TxEmpty = 0;	/* not empty in the THR until it shifts out */
+
+     }
+     return 0;
+  }
+
+  int HardwareSerial::available() {
+    if ( PortNum == 0 )
+{
+  return (UART0RxQueueWritePos + UARTRXQUEUESIZE - UART0RxQueueReadPos) % UARTRXQUEUESIZE;
+}
+if ( PortNum == 1 )
+{
+  return (UART1RxQueueWritePos + UARTRXQUEUESIZE - UART1RxQueueReadPos) % UARTRXQUEUESIZE;
+}
+if ( PortNum == 2 )
+{
+  return (UART2RxQueueWritePos + UARTRXQUEUESIZE - UART2RxQueueReadPos) % UARTRXQUEUESIZE;
+}
+if ( PortNum == 3 )
+{
+  return (UART3RxQueueWritePos + UARTRXQUEUESIZE - UART3RxQueueReadPos) % UARTRXQUEUESIZE;
+}
+return 0;
+  }
+
+  void HardwareSerial::flush() {
+    if ( PortNum == 0 )
+{
+  UART0RxQueueWritePos = 0;
+  UART0RxQueueReadPos = 0;
+
+}
+if ( PortNum == 1 )
+{
+  UART1RxQueueWritePos = 0;
+  UART1RxQueueReadPos = 0;
+}
+if ( PortNum == 2 )
+{
+  UART2RxQueueWritePos = 0;
+  UART2RxQueueReadPos = 0;
+}
+if ( PortNum == 3 )
+{
+  UART3RxQueueWritePos = 0;
+  UART3RxQueueReadPos = 0;
+}
+return;
+  }
+
+  void HardwareSerial::printf(const char *format, ...) {
+    static char buffer[256];
+    va_list vArgs;
+    va_start(vArgs, format);
+    int length = vsnprintf((char *) buffer, 256, (char const *) format, vArgs);
+    va_end(vArgs);
+    if (length > 0 && length < 256) {
+        for (int i = 0; i < length;) {
+          write(buffer[i]);
+            ++i;
+          }
+        }
+    }
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*****************************************************************************
+** Function name:		UART0_IRQHandler
+**
+** Descriptions:		UART0 interrupt handler
+**
+** parameters:			None
+** Returned value:		None
+**
+*****************************************************************************/
+void UART0_IRQHandler (void)
+{
+  uint8_t IIRValue, LSRValue;
+  uint8_t Dummy = Dummy;
+
+  IIRValue = LPC_UART0->IIR;
+
+  IIRValue >>= 1;			/* skip pending bit in IIR */
+  IIRValue &= 0x07;			/* check bit 1~3, interrupt identification */
+  if ( IIRValue == IIR_RLS )		/* Receive Line Status */
+  {
+	LSRValue = LPC_UART0->LSR;
+	/* Receive Line Status */
+	if ( LSRValue & (LSR_OE|LSR_PE|LSR_FE|LSR_RXFE|LSR_BI) )
+	{
+	  /* There are errors or break interrupt */
+	  /* Read LSR will clear the interrupt */
+	  UART0Status = LSRValue;
+	  Dummy = LPC_UART0->RBR;		/* Dummy read on RX to clear
+							interrupt, then bail out */
+	  return;
+	}
+	if ( LSRValue & LSR_RDR )	/* Receive Data Ready */
+	{
+	  /* If no error on RLS, normal ready, save into the data buffer. */
+	  /* Note: read RBR will clear the interrupt */
+		  if ((UART0RxQueueWritePos+1) % UARTRXQUEUESIZE != UART0RxQueueReadPos)
+		  {
+			  UART0Buffer[UART0RxQueueWritePos] = LPC_UART0->RBR;
+			  UART0RxQueueWritePos = (UART0RxQueueWritePos+1) % UARTRXQUEUESIZE;
+		  }
+		  else
+			  dummy = LPC_UART0->RBR;;
+	}
+  }
+  else if ( IIRValue == IIR_RDA )	/* Receive Data Available */
+  {
+	/* Receive Data Available */
+	  if ((UART0RxQueueWritePos+1) % UARTRXQUEUESIZE != UART0RxQueueReadPos)
+	  {
+		  UART0Buffer[UART0RxQueueWritePos] = LPC_UART0->RBR;
+		  UART0RxQueueWritePos = (UART0RxQueueWritePos+1) % UARTRXQUEUESIZE;
+	  }
+	  else
+		  dummy = LPC_UART1->RBR;;
+  }
+  else if ( IIRValue == IIR_CTI )	/* Character timeout indicator */
+  {
+	/* Character Time-out indicator */
+	UART0Status |= 0x100;		/* Bit 9 as the CTI error */
+  }
+  else if ( IIRValue == IIR_THRE )	/* THRE, transmit holding register empty */
+  {
+	/* THRE interrupt */
+	LSRValue = LPC_UART0->LSR;		/* Check status in the LSR to see if
+									valid data in U0THR or not */
+	if ( LSRValue & LSR_THRE )
+	{
+	  UART0TxEmpty = 1;
+	}
+	else
+	{
+	  UART0TxEmpty = 0;
+	}
+  }
+}
+
+/*****************************************************************************
+** Function name:		UART1_IRQHandler
+**
+** Descriptions:		UART1 interrupt handler
+**
+** parameters:			None
+** Returned value:		None
+**
+*****************************************************************************/
+void UART1_IRQHandler (void)
+{
+  uint8_t IIRValue, LSRValue;
+  uint8_t Dummy = Dummy;
+
+  IIRValue = LPC_UART1->IIR;
+
+  IIRValue >>= 1;			/* skip pending bit in IIR */
+  IIRValue &= 0x07;			/* check bit 1~3, interrupt identification */
+  if ( IIRValue == IIR_RLS )		/* Receive Line Status */
+  {
+	LSRValue = LPC_UART1->LSR;
+	/* Receive Line Status */
+	if ( LSRValue & (LSR_OE|LSR_PE|LSR_FE|LSR_RXFE|LSR_BI) )
+	{
+	  /* There are errors or break interrupt */
+	  /* Read LSR will clear the interrupt */
+	  UART1Status = LSRValue;
+	  Dummy = LPC_UART1->RBR;		/* Dummy read on RX to clear
+								interrupt, then bail out */
+	  return;
+	}
+	if ( LSRValue & LSR_RDR )	/* Receive Data Ready */
+	{
+	  /* If no error on RLS, normal ready, save into the data buffer. */
+	  /* Note: read RBR will clear the interrupt */
+	  if ((UART1RxQueueWritePos+1) % UARTRXQUEUESIZE != UART1RxQueueReadPos)
+	  {
+		  UART1Buffer[UART1RxQueueWritePos] = LPC_UART1->RBR;
+		  UART1RxQueueWritePos =(UART1RxQueueWritePos+1) % UARTRXQUEUESIZE;
+	  }
+	  else
+		  dummy = LPC_UART1->RBR;;
+	}
+  }
+  else if ( IIRValue == IIR_RDA )	/* Receive Data Available */
+  {
+	/* Receive Data Available */
+	  if ((UART1RxQueueWritePos+1) % UARTRXQUEUESIZE != UART1RxQueueReadPos)
+	  {
+		  UART1Buffer[UART1RxQueueWritePos] = LPC_UART1->RBR;
+		  UART1RxQueueWritePos = (UART1RxQueueWritePos+1) % UARTRXQUEUESIZE;
+	  }
+	  else
+		  dummy = LPC_UART1->RBR;;
+  }
+  else if ( IIRValue == IIR_CTI )	/* Character timeout indicator */
+  {
+	/* Character Time-out indicator */
+	UART1Status |= 0x100;		/* Bit 9 as the CTI error */
+  }
+  else if ( IIRValue == IIR_THRE )	/* THRE, transmit holding register empty */
+  {
+	/* THRE interrupt */
+	LSRValue = LPC_UART1->LSR;		/* Check status in the LSR to see if
+								valid data in U0THR or not */
+	if ( LSRValue & LSR_THRE )
+	{
+	  UART1TxEmpty = 1;
+	}
+	else
+	{
+	  UART1TxEmpty = 0;
+	}
+  }
+
+}
+/*****************************************************************************
+** Function name:		UART2_IRQHandler
+**
+** Descriptions:		UART2 interrupt handler
+**
+** parameters:			None
+** Returned value:		None
+**
+*****************************************************************************/
+void UART2_IRQHandler (void)
+{
+  uint8_t IIRValue, LSRValue;
+  uint8_t Dummy = Dummy;
+
+  IIRValue = LPC_UART2->IIR;
+
+  IIRValue >>= 1;			/* skip pending bit in IIR */
+  IIRValue &= 0x07;			/* check bit 1~3, interrupt identification */
+  if ( IIRValue == IIR_RLS )		/* Receive Line Status */
+  {
+	LSRValue = LPC_UART2->LSR;
+	/* Receive Line Status */
+	if ( LSRValue & (LSR_OE|LSR_PE|LSR_FE|LSR_RXFE|LSR_BI) )
+	{
+	  /* There are errors or break interrupt */
+	  /* Read LSR will clear the interrupt */
+	  UART2Status = LSRValue;
+	  Dummy = LPC_UART2->RBR;		/* Dummy read on RX to clear
+							interrupt, then bail out */
+	  return;
+	}
+	if ( LSRValue & LSR_RDR )	/* Receive Data Ready */
+	{
+	  /* If no error on RLS, normal ready, save into the data buffer. */
+	  /* Note: read RBR will clear the interrupt */
+		 if ((UART2RxQueueWritePos+1) % UARTRXQUEUESIZE != UART2RxQueueReadPos)
+		  {
+			  UART2Buffer[UART2RxQueueWritePos] = LPC_UART2->RBR;
+			  UART2RxQueueWritePos = (UART2RxQueueWritePos+1) % UARTRXQUEUESIZE;
+		  }
+	}
+  }
+  else if ( IIRValue == IIR_RDA )	/* Receive Data Available */
+  {
+	/* Receive Data Available */
+	  if ((UART2RxQueueWritePos+1) % UARTRXQUEUESIZE != UART2RxQueueReadPos)
+	  {
+		  UART2Buffer[UART2RxQueueWritePos] = LPC_UART2->RBR;
+		  UART2RxQueueWritePos = (UART2RxQueueWritePos+1) % UARTRXQUEUESIZE;
+	  }
+	  else
+		  dummy = LPC_UART2->RBR;;
+  }
+  else if ( IIRValue == IIR_CTI )	/* Character timeout indicator */
+  {
+	/* Character Time-out indicator */
+	UART2Status |= 0x100;		/* Bit 9 as the CTI error */
+  }
+  else if ( IIRValue == IIR_THRE )	/* THRE, transmit holding register empty */
+  {
+	/* THRE interrupt */
+	LSRValue = LPC_UART2->LSR;		/* Check status in the LSR to see if
+									valid data in U0THR or not */
+	if ( LSRValue & LSR_THRE )
+	{
+	  UART2TxEmpty = 1;
+	}
+	else
+	{
+	  UART2TxEmpty = 0;
+	}
+  }
+}
+/*****************************************************************************
+** Function name:		UART3_IRQHandler
+**
+** Descriptions:		UART0 interrupt handler
+**
+** parameters:			None
+** Returned value:		None
+**
+*****************************************************************************/
+void UART3_IRQHandler (void)
+{
+  uint8_t IIRValue, LSRValue;
+  uint8_t Dummy = Dummy;
+
+  IIRValue = LPC_UART3->IIR;
+
+  IIRValue >>= 1;			/* skip pending bit in IIR */
+  IIRValue &= 0x07;			/* check bit 1~3, interrupt identification */
+  if ( IIRValue == IIR_RLS )		/* Receive Line Status */
+  {
+	LSRValue = LPC_UART3->LSR;
+	/* Receive Line Status */
+	if ( LSRValue & (LSR_OE|LSR_PE|LSR_FE|LSR_RXFE|LSR_BI) )
+	{
+	  /* There are errors or break interrupt */
+	  /* Read LSR will clear the interrupt */
+	  UART3Status = LSRValue;
+	  Dummy = LPC_UART3->RBR;		/* Dummy read on RX to clear
+							interrupt, then bail out */
+	  return;
+	}
+	if ( LSRValue & LSR_RDR )	/* Receive Data Ready */
+	{
+	  /* If no error on RLS, normal ready, save into the data buffer. */
+	  /* Note: read RBR will clear the interrupt */
+		 if ((UART3RxQueueWritePos+1) % UARTRXQUEUESIZE != UART3RxQueueReadPos)
+		  {
+			  UART3Buffer[UART3RxQueueWritePos] = LPC_UART3->RBR;
+			  UART3RxQueueWritePos = (UART3RxQueueWritePos+1) % UARTRXQUEUESIZE;
+		  }
+	}
+  }
+  else if ( IIRValue == IIR_RDA )	/* Receive Data Available */
+  {
+	/* Receive Data Available */
+	  if ((UART3RxQueueWritePos+1) % UARTRXQUEUESIZE != UART3RxQueueReadPos)
+	  {
+		  UART3Buffer[UART3RxQueueWritePos] = LPC_UART3->RBR;
+		  UART3RxQueueWritePos = (UART3RxQueueWritePos+1) % UARTRXQUEUESIZE;
+	  }
+	  else
+		  dummy = LPC_UART3->RBR;;
+  }
+  else if ( IIRValue == IIR_CTI )	/* Character timeout indicator */
+  {
+	/* Character Time-out indicator */
+	UART3Status |= 0x100;		/* Bit 9 as the CTI error */
+  }
+  else if ( IIRValue == IIR_THRE )	/* THRE, transmit holding register empty */
+  {
+	/* THRE interrupt */
+	LSRValue = LPC_UART3->LSR;		/* Check status in the LSR to see if
+									valid data in U0THR or not */
+	if ( LSRValue & LSR_THRE )
+	{
+	  UART3TxEmpty = 1;
+	}
+	else
+	{
+	  UART3TxEmpty = 0;
+	}
+  }
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/Marlin/src/HAL/HAL_LPC1768/HardwareSerial.h b/Marlin/src/HAL/HAL_LPC1768/HardwareSerial.h
new file mode 100644
index 0000000000..90a773dda3
--- /dev/null
+++ b/Marlin/src/HAL/HAL_LPC1768/HardwareSerial.h
@@ -0,0 +1,149 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef HARDWARE_SERIAL_H_
+#define HARDWARE_SERIAL_H_
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <Stream.h>
+
+extern "C" {
+  #include <debug_frmwrk.h>
+
+//#include <lpc17xx_uart.h>
+}
+
+#define IER_RBR		0x01
+#define IER_THRE	0x02
+#define IER_RLS		0x04
+
+#define IIR_PEND	0x01
+#define IIR_RLS		0x03
+#define IIR_RDA		0x02
+#define IIR_CTI		0x06
+#define IIR_THRE	0x01
+
+#define LSR_RDR		0x01
+#define LSR_OE		0x02
+#define LSR_PE		0x04
+#define LSR_FE		0x08
+#define LSR_BI		0x10
+#define LSR_THRE	0x20
+#define LSR_TEMT	0x40
+#define LSR_RXFE	0x80
+
+#define UARTRXQUEUESIZE		0x10
+
+class HardwareSerial : public Stream {
+private:
+uint8_t PortNum;
+uint32_t baudrate;
+
+public:
+  HardwareSerial(uint32_t uart) :
+    PortNum(uart)
+    {
+    }
+
+  void begin(uint32_t baudrate);
+  int read();
+  size_t write(uint8_t send);
+  int available();
+  void flush();
+  void printf(const char *format, ...);
+  int peek() {
+    return 0;
+  };
+
+
+  operator bool() {
+    return true;
+  }
+
+    void print(const char value[]) {
+      printf("%s" , value);
+    }
+    void print(char value, int = 0) {
+      printf("%c" , value);
+    }
+    void print(unsigned char value, int = 0) {
+      printf("%u" , value);
+    }
+    void print(int value, int = 0) {
+      printf("%d" , value);
+    }
+    void print(unsigned int value, int = 0) {
+      printf("%u" , value);
+    }
+    void print(long value, int = 0) {
+      printf("%ld" , value);
+    }
+    void print(unsigned long value, int = 0) {
+      printf("%lu" , value);
+    }
+
+    void print(float value, int round = 6) {
+      printf("%f" , value);
+    }
+    void print(double value, int round = 6) {
+      printf("%f" , value );
+    }
+
+    void println(const char value[]) {
+      printf("%s\n" , value);
+    }
+    void println(char value, int = 0) {
+      printf("%c\n" , value);
+    }
+    void println(unsigned char value, int = 0) {
+      printf("%u\r\n" , value);
+    }
+    void println(int value, int = 0) {
+      printf("%d\n" , value);
+    }
+    void println(unsigned int value, int = 0) {
+      printf("%u\n" , value);
+    }
+    void println(long value, int = 0) {
+      printf("%ld\n" , value);
+    }
+    void println(unsigned long value, int = 0) {
+      printf("%lu\n" , value);
+    }
+    void println(float value, int round = 6) {
+      printf("%f\n" , value );
+    }
+    void println(double value, int round = 6) {
+      printf("%f\n" , value );
+    }
+    void println(void) {
+      print('\n');
+    }
+
+};
+//extern HardwareSerial Serial0;
+//extern HardwareSerial Serial1;
+//extern HardwareSerial Serial2;
+extern HardwareSerial Serial3;
+
+#endif /* MARLIN_SRC_HAL_HAL_SERIAL_H_ */
diff --git a/Marlin/src/HAL/HAL_LPC1768/SoftwareSerial.cpp b/Marlin/src/HAL/HAL_LPC1768/SoftwareSerial.cpp
new file mode 100644
index 0000000000..9b5eab549b
--- /dev/null
+++ b/Marlin/src/HAL/HAL_LPC1768/SoftwareSerial.cpp
@@ -0,0 +1,398 @@
+/*
+SoftwareSerial.cpp (formerly NewSoftSerial.cpp) -
+Multi-instance software serial library for Arduino/Wiring
+-- Interrupt-driven receive and other improvements by ladyada
+   (http://ladyada.net)
+-- Tuning, circular buffer, derivation from class Print/Stream,
+   multi-instance support, porting to 8MHz processors,
+   various optimizations, PROGMEM delay tables, inverse logic and
+   direct port writing by Mikal Hart (http://www.arduiniana.org)
+-- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com)
+-- 20MHz processor support by Garrett Mace (http://www.macetech.com)
+-- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/)
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+The latest version of this library can always be found at
+http://arduiniana.org.
+*/
+
+
+//
+// Includes
+//
+//#include <WInterrupts.h>
+#include "../../../macros.h"
+#include "../HAL.h"
+#include <stdint.h>
+#include <stdarg.h>
+#include "arduino.h"
+#include "pinmapping.h"
+#include "pinmap_re_arm.h"
+#include "fastio.h"
+#include "SoftwareSerial.h"
+
+void GpioEnableInt(uint32_t port, uint32_t pin, uint32_t mode);
+void GpioDisableInt(uint32_t port, uint32_t pin);
+//
+// Statics
+//
+SoftwareSerial *SoftwareSerial::active_object = 0;
+unsigned char SoftwareSerial::_receive_buffer[_SS_MAX_RX_BUFF];
+volatile uint8_t SoftwareSerial::_receive_buffer_tail = 0;
+volatile uint8_t SoftwareSerial::_receive_buffer_head = 0;
+
+typedef struct _DELAY_TABLE
+{
+  long baud;
+  uint16_t rx_delay_centering;
+  uint16_t rx_delay_intrabit;
+  uint16_t rx_delay_stopbit;
+  uint16_t tx_delay;
+} DELAY_TABLE;
+
+// rough delay estimation
+static const DELAY_TABLE table[] =
+{
+  //baud    |rxcenter|rxintra |rxstop  |tx
+  { 250000,   2,      4,       4,       4,   }, //Done but not good due to instruction cycle error
+  { 115200,   4,      8,       8,       8,   }, //Done but not good due to instruction cycle error
+  //{ 74880,   69,       139,       62,      162,  }, // estimation
+//  { 57600,   100,       185,      1,       208,  }, // Done but not good due to instruction cycle error
+  //{ 38400,   13,      26,      26,      26,  }, // Done
+  //{ 19200,   26,      52,      52,      52,  }, // Done
+  { 9600,    52,      104,     104,     104, }, // Done
+  //{ 4800,    104,     208,     208,     208, },
+  //{ 2400,    208,     417,     417,     417, },
+  //{ 1200,    416,    833,      833,     833,},
+};
+
+//
+// Private methods
+//
+
+#if 0
+/* static */
+inline void SoftwareSerial::tunedDelay(uint32_t count) {
+
+	asm volatile(
+
+    "mov r3, %[loopsPerMicrosecond] \n\t" //load the initial loop counter
+    "1: \n\t"
+    "sub r3, r3, #1 \n\t"
+    "bne 1b \n\t"
+
+    ://empty output list
+    :[loopsPerMicrosecond] "r" (count)
+    :"r3", "cc" //clobber list
+  );
+
+}
+#else
+inline void SoftwareSerial::tunedDelay(uint32_t count) {
+  delayMicroseconds(count);
+}
+#endif
+
+// This function sets the current object as the "listening"
+// one and returns true if it replaces another
+bool SoftwareSerial::listen()
+{
+  if (!_rx_delay_stopbit)
+    return false;
+
+  if (active_object != this)
+  {
+    if (active_object)
+      active_object->stopListening();
+
+    _buffer_overflow = false;
+    _receive_buffer_head = _receive_buffer_tail = 0;
+    active_object = this;
+
+    setRxIntMsk(true);
+    return true;
+  }
+
+  return false;
+}
+
+// Stop listening. Returns true if we were actually listening.
+bool SoftwareSerial::stopListening()
+{
+  if (active_object == this)
+  {
+    setRxIntMsk(false);
+    active_object = NULL;
+    return true;
+  }
+  return false;
+}
+
+//
+// The receive routine called by the interrupt handler
+//
+void SoftwareSerial::recv()
+{
+  uint8_t d = 0;
+
+  // If RX line is high, then we don't see any start bit
+  // so interrupt is probably not for us
+  if (_inverse_logic ? rx_pin_read() : !rx_pin_read())
+  {
+    // Disable further interrupts during reception, this prevents
+    // triggering another interrupt directly after we return, which can
+    // cause problems at higher baudrates.
+    setRxIntMsk(false);//__disable_irq();//
+
+    // Wait approximately 1/2 of a bit width to "center" the sample
+    tunedDelay(_rx_delay_centering);
+    // Read each of the 8 bits
+    for (uint8_t i=8; i > 0; --i)
+    {
+	  tunedDelay(_rx_delay_intrabit);
+      d >>= 1;
+      if (rx_pin_read())
+        d |= 0x80;
+    }
+
+    if (_inverse_logic)
+      d = ~d;
+
+    // if buffer full, set the overflow flag and return
+    uint8_t next = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF;
+    if (next != _receive_buffer_head)
+    {
+      // save new data in buffer: tail points to where byte goes
+      _receive_buffer[_receive_buffer_tail] = d; // save new byte
+      _receive_buffer_tail = next;
+    }
+    else
+    {
+      _buffer_overflow = true;
+    }
+	tunedDelay(_rx_delay_stopbit);
+    // Re-enable interrupts when we're sure to be inside the stop bit
+	setRxIntMsk(true);//__enable_irq();//
+
+  }
+}
+
+uint32_t SoftwareSerial::rx_pin_read()
+{
+  return digitalRead(_receivePin);
+}
+
+//
+// Interrupt handling
+//
+
+/* static */
+inline void SoftwareSerial::handle_interrupt()
+{
+  if (active_object)
+  {
+    active_object->recv();
+  }
+}
+extern "C" void intWrapper() {
+  SoftwareSerial::handle_interrupt();
+}
+//
+// Constructor
+//
+SoftwareSerial::SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic /* = false */) :
+  _rx_delay_centering(0),
+  _rx_delay_intrabit(0),
+  _rx_delay_stopbit(0),
+  _tx_delay(0),
+  _buffer_overflow(false),
+  _inverse_logic(inverse_logic)
+{
+  setTX(transmitPin);
+  setRX(receivePin);
+
+}
+
+//
+// Destructor
+//
+SoftwareSerial::~SoftwareSerial()
+{
+  end();
+}
+
+void SoftwareSerial::setTX(uint8_t tx)
+{
+  // First write, then set output. If we do this the other way around,
+  // the pin would be output low for a short while before switching to
+  // output hihg. Now, it is input with pullup for a short while, which
+  // is fine. With inverse logic, either order is fine.
+
+  digitalWrite(tx, _inverse_logic ? LOW : HIGH);
+  pinMode(tx,OUTPUT);
+  _transmitPin = tx;
+
+}
+
+void SoftwareSerial::setRX(uint8_t rx)
+{
+  pinMode(rx, INPUT_PULLUP); // pullup for normal logic!
+  //if (!_inverse_logic)
+  // digitalWrite(rx, HIGH);
+  _receivePin = rx;
+  _receivePort = pin_map[rx].port;
+  _receivePortPin = pin_map[rx].pin;
+/*  GPIO_T * rxPort = digitalPinToPort(rx);
+  _receivePortRegister = portInputRegister(rxPort);
+  _receiveBitMask = digitalPinToBitMask(rx);*/
+
+}
+
+//
+// Public methods
+//
+
+void SoftwareSerial::begin(long speed)
+{
+  _rx_delay_centering = _rx_delay_intrabit = _rx_delay_stopbit = _tx_delay = 0;
+
+  for(uint8_t i = 0; i < sizeof(table)/sizeof(table[0]); ++i)
+  {
+    long baud = table[i].baud;
+    if(baud == speed)
+    {
+      _rx_delay_centering = table[i].rx_delay_centering;
+      _rx_delay_intrabit = table[i].rx_delay_intrabit;
+      _rx_delay_stopbit = table[i].rx_delay_stopbit;
+      _tx_delay = table[i].tx_delay;
+      break;
+    }
+  }
+
+  attachInterrupt(_receivePin, intWrapper, CHANGE); //this->handle_interrupt, CHANGE);
+
+  listen();
+  tunedDelay(_tx_delay);
+
+}
+
+void SoftwareSerial::setRxIntMsk(bool enable)
+{
+    if (enable)
+        GpioEnableInt(_receivePort,_receivePin,CHANGE);
+    else
+        GpioDisableInt(_receivePort,_receivePin);
+}
+
+void SoftwareSerial::end()
+{
+  stopListening();
+}
+
+
+// Read data from buffer
+int SoftwareSerial::read()
+{
+  if (!isListening())
+    return -1;
+
+  // Empty buffer?
+  if (_receive_buffer_head == _receive_buffer_tail)
+    return -1;
+
+  // Read from "head"
+  uint8_t d = _receive_buffer[_receive_buffer_head]; // grab next byte
+  _receive_buffer_head = (_receive_buffer_head + 1) % _SS_MAX_RX_BUFF;
+  return d;
+}
+
+int SoftwareSerial::available()
+{
+  if (!isListening())
+    return 0;
+
+  return (_receive_buffer_tail + _SS_MAX_RX_BUFF - _receive_buffer_head) % _SS_MAX_RX_BUFF;
+}
+
+size_t SoftwareSerial::write(uint8_t b)
+{
+  // By declaring these as local variables, the compiler will put them
+  // in registers _before_ disabling interrupts and entering the
+  // critical timing sections below, which makes it a lot easier to
+  // verify the cycle timings
+
+  bool inv = _inverse_logic;
+  uint16_t delay = _tx_delay;
+
+  if(inv)
+	  b = ~b;
+
+  cli();  // turn off interrupts for a clean txmit
+
+  // Write the start bit
+  if (inv)
+    digitalWrite(_transmitPin, 1);
+  else
+    digitalWrite(_transmitPin, 0);
+
+  tunedDelay(delay);
+
+  // Write each of the 8 bits
+  for (uint8_t i = 8; i > 0; --i)
+  {
+    if (b & 1) // choose bit
+      digitalWrite(_transmitPin, 1); // send 1 //(GPIO_Desc[_transmitPin].P)->DOUT |= GPIO_Desc[_transmitPin].bit;
+    else
+      digitalWrite(_transmitPin, 0); // send 0 //(GPIO_Desc[_transmitPin].P)->DOUT &= ~GPIO_Desc[_transmitPin].bit;
+
+    tunedDelay(delay);
+    b >>= 1;
+  }
+
+  // restore pin to natural state
+  if (inv)
+    digitalWrite(_transmitPin, 0);
+  else
+    digitalWrite(_transmitPin, 1);
+
+	sei(); // turn interrupts back on
+  tunedDelay(delay);
+
+  return 1;
+}
+
+void SoftwareSerial::flush()
+{
+  if (!isListening())
+    return;
+
+  cli();
+  _receive_buffer_head = _receive_buffer_tail = 0;
+  sei();
+}
+
+int SoftwareSerial::peek()
+{
+  if (!isListening())
+    return -1;
+
+  // Empty buffer?
+  if (_receive_buffer_head == _receive_buffer_tail)
+    return -1;
+
+  // Read from "head"
+  return _receive_buffer[_receive_buffer_head];
+}
diff --git a/Marlin/src/HAL/HAL_LPC1768/SoftwareSerial.h b/Marlin/src/HAL/HAL_LPC1768/SoftwareSerial.h
new file mode 100644
index 0000000000..e78c59744c
--- /dev/null
+++ b/Marlin/src/HAL/HAL_LPC1768/SoftwareSerial.h
@@ -0,0 +1,119 @@
+/*
+SoftwareSerial.h (formerly NewSoftSerial.h) -
+Multi-instance software serial library for Arduino/Wiring
+-- Interrupt-driven receive and other improvements by ladyada
+   (http://ladyada.net)
+-- Tuning, circular buffer, derivation from class Print/Stream,
+   multi-instance support, porting to 8MHz processors,
+   various optimizations, PROGMEM delay tables, inverse logic and
+   direct port writing by Mikal Hart (http://www.arduiniana.org)
+-- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com)
+-- 20MHz processor support by Garrett Mace (http://www.macetech.com)
+-- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/)
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+The latest version of this library can always be found at
+http://arduiniana.org.
+*/
+
+#ifndef SoftwareSerial_h
+#define SoftwareSerial_h
+
+#include "arduino.h"
+#include <inttypes.h>
+//#include "serial.h"
+ #include <Stream.h>
+#include <Print.h>
+
+/******************************************************************************
+* Definitions
+******************************************************************************/
+
+#define _SS_MAX_RX_BUFF 64 // RX buffer size
+
+class SoftwareSerial : public Stream
+{
+private:
+  // per object data
+  uint8_t _receivePin;
+  uint8_t _transmitPin;
+//  uint32_t _receiveBitMask; // for rx interrupts
+  uint32_t _receivePort;
+  uint32_t _receivePortPin;
+
+
+  // Expressed as 4-cycle delays (must never be 0!)
+  uint16_t _rx_delay_centering;
+  uint16_t _rx_delay_intrabit;
+  uint16_t _rx_delay_stopbit;
+  uint16_t _tx_delay;
+
+  uint16_t _buffer_overflow:1;
+  uint16_t _inverse_logic:1;
+
+  // static data
+  static unsigned char _receive_buffer[_SS_MAX_RX_BUFF];
+  static volatile uint8_t _receive_buffer_tail;
+  static volatile uint8_t _receive_buffer_head;
+  static SoftwareSerial *active_object;
+
+  // private methods
+  void recv() __attribute__((__always_inline__));
+  uint32_t rx_pin_read();
+  void tx_pin_write(uint8_t pin_state) __attribute__((__always_inline__));
+  void setTX(uint8_t transmitPin);
+  void setRX(uint8_t receivePin);
+  void setRxIntMsk(bool enable) __attribute__((__always_inline__));
+
+  // private static method for timing
+  static inline void tunedDelay(uint32_t delay);
+
+public:
+  // public methods
+
+  SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic = false);
+  ~SoftwareSerial();
+  void begin(long speed);
+  bool listen();
+  void end();
+  bool isListening() { return this == active_object; }
+  bool stopListening();
+  bool overflow() { bool ret = _buffer_overflow; if (ret) _buffer_overflow = false; return ret; }
+  int peek();
+
+  virtual size_t write(uint8_t byte);
+  virtual int read();
+  virtual int available();
+  virtual void flush();
+  operator bool() { return true; }
+
+  using Print::write;
+  //using HalSerial::write;
+
+  // public only for easy access by interrupt handlers
+  static inline void handle_interrupt() __attribute__((__always_inline__));
+};
+
+// Arduino 0012 workaround
+#undef int
+#undef char
+#undef long
+#undef byte
+#undef float
+#undef abs
+#undef round
+
+#endif
diff --git a/Marlin/src/HAL/HAL_LPC1768/WInterrupts.cpp b/Marlin/src/HAL/HAL_LPC1768/WInterrupts.cpp
new file mode 100644
index 0000000000..cfb591b0a2
--- /dev/null
+++ b/Marlin/src/HAL/HAL_LPC1768/WInterrupts.cpp
@@ -0,0 +1,224 @@
+/*
+  Copyright (c) 2011-2012 Arduino.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "../../../macros.h"
+#include "../HAL.h"
+#include "arduino.h"
+#include "pinmapping.h"
+//#include "HAL_timers.h"
+#include "fastio.h"
+
+#define GNUM 31
+
+typedef void (*interruptCB)(void);
+
+static interruptCB callbacksP0[GNUM];
+static interruptCB callbacksP2[GNUM];
+
+	extern "C" void GpioEnableInt(uint32_t port, uint32_t pin, uint32_t mode);
+	extern "C" void GpioDisableInt(uint32_t port, uint32_t pin);
+
+//void deadloop(void) {}
+
+/* Configure PIO interrupt sources */
+static void __initialize() {
+	int i;
+	for (i=0; i<GNUM; i++) {
+		callbacksP0[i] = 0;
+		callbacksP2[i] = 0;
+		}
+NVIC_EnableIRQ(EINT3_IRQn);
+}
+
+void attachInterrupt(uint32_t pin, void (*callback)(void), uint32_t mode)
+{
+	static int enabled = 0;
+
+	if(!INTERRUPT_PIN(pin)) return;
+
+	if (!enabled) {
+		__initialize();
+		enabled = 1;
+	}
+	uint8_t myport = pin_map[pin].port;
+	uint8_t mypin = pin_map[pin].pin;
+
+
+	if (myport == 0 )
+		callbacksP0[mypin] = callback;
+	else
+		callbacksP2[mypin] = callback;
+
+	// Enable interrupt
+		GpioEnableInt(myport,mypin,mode);
+}
+
+void detachInterrupt(uint32_t pin)
+{
+	if(!INTERRUPT_PIN(pin)) return;
+
+  uint8_t myport = pin_map[pin].port;
+  uint8_t mypin = pin_map[pin].pin;
+
+	// Disable interrupt
+	GpioDisableInt(myport,mypin);
+
+//unset callback
+	if (myport == 0 )
+		callbacksP0[mypin] = 0;
+	else //if (myport == 2 )
+		callbacksP2[mypin] = 0;
+	}
+
+
+	extern "C" void GpioEnableInt(uint32_t port, uint32_t pin, uint32_t mode) {
+	//pin here is the processor pin, not logical pin
+	if (port==0) {
+		LPC_GPIOINT->IO0IntClr = (1 << pin);
+		if (mode ==RISING) {
+			LPC_GPIOINT->IO0IntEnR |= (1<<pin);
+  		LPC_GPIOINT->IO0IntEnF &= ~(1<<pin);
+		}
+		else if (mode==FALLING) {
+			LPC_GPIOINT->IO0IntEnF |= (1<<pin);
+  		LPC_GPIOINT->IO0IntEnR &= ~(1<<pin);
+		}
+		else if (mode==CHANGE) {
+		LPC_GPIOINT->IO0IntEnR |= (1<<pin);
+		LPC_GPIOINT->IO0IntEnF |= (1<<pin);
+		}
+	}
+	else{
+		LPC_GPIOINT->IO2IntClr = (1 << pin);
+		if (mode ==RISING) {
+			LPC_GPIOINT->IO2IntEnR |= (1<<pin);
+			LPC_GPIOINT->IO2IntEnF &= ~(1<<pin);
+		}
+		else if (mode==FALLING) {
+			LPC_GPIOINT->IO2IntEnF |= (1<<pin);
+			LPC_GPIOINT->IO2IntEnR &= ~(1<<pin);
+		}
+		else if (mode==CHANGE) {
+		LPC_GPIOINT->IO2IntEnR |= (1<<pin);
+		LPC_GPIOINT->IO2IntEnF |= (1<<pin);
+		}
+	}
+}
+extern "C"  void GpioDisableInt(uint32_t port, uint32_t pin)
+{
+	if (port==0){
+		LPC_GPIOINT->IO0IntEnR &= ~(1<<pin);
+		LPC_GPIOINT->IO0IntEnF &= ~(1<<pin);
+		LPC_GPIOINT->IO0IntClr = 1 << pin;
+	}
+	else {
+		LPC_GPIOINT->IO2IntEnR &= ~(1<<pin);
+		LPC_GPIOINT->IO2IntEnF &= ~(1<<pin);
+		LPC_GPIOINT->IO2IntClr = 1 << pin;
+	}
+}
+
+bool isPowerOf2(unsigned int n)
+
+{
+
+    return n == 1 || (n & (n-1)) == 0;
+
+}
+
+#if 0
+extern "C" void EINT3_IRQHandler () {
+	LPC_GPIOINT->IO0IntClr = LPC_GPIOINT->IO2IntClr = 0xFFFFFFFF;
+	TOGGLE(13);
+	//NVIC_ClearPendingIRQ(EINT3_IRQn);
+}
+#else
+extern "C" void EINT3_IRQHandler(void)
+{
+	// Read in all current interrupt registers. We do this once as the
+// GPIO interrupt registers are on the APB bus, and this is slow.
+uint32_t rise0 = LPC_GPIOINT->IO0IntStatR;
+uint32_t fall0 = LPC_GPIOINT->IO0IntStatF;
+uint32_t rise2 = LPC_GPIOINT->IO2IntStatR;
+uint32_t fall2 = LPC_GPIOINT->IO2IntStatF;
+//Clear teh interrupts ASAP
+LPC_GPIOINT->IO0IntClr = LPC_GPIOINT->IO2IntClr = 0xFFFFFFFF;
+NVIC_ClearPendingIRQ(EINT3_IRQn);
+uint8_t bitloc;
+if (rise0 == 0)
+	goto fall0;
+	/* multiple pins changes happened.*/
+	while(rise0 > 0) {      //Continue as long as there are interrupts pending
+			bitloc = 31 - __CLZ(rise0); //CLZ returns number of leading zeros, 31 minus that is location of first pending interrupt
+			if (callbacksP0[bitloc]!=0)
+				callbacksP0[bitloc]();
+			rise0 -= 1<<bitloc;
+	}
+fall0:
+if (fall0==0)
+	goto rise2;
+/* if (isPowerOf2(fall0) && callbacksP0[31 - __CLZ(rise0)])
+  callbacksP0[31 - __CLZ(rise0)](); */
+	//LPC_GPIOINT->IO0IntClr = fall0;*/
+else {
+while(fall0 > 0) {
+		bitloc = 31 - __CLZ(fall0);
+		if (callbacksP0[bitloc]!=0)
+			callbacksP0[bitloc]();
+		fall0 -= 1<<bitloc;
+  }
+}
+rise2:
+if (rise2==0)
+	goto fall2;
+/*if ((rise2 & (rise2 - 1)) == 0) {
+  callbacksP2[rise2]();
+	//LPC_GPIOINT->IO2IntClr = rise2;
+}*/
+else {
+while(rise2 > 0) {
+		bitloc = 31 - __CLZ(rise2);
+		if (callbacksP2[bitloc]!=0)
+			callbacksP2[bitloc]();
+		//LPC_GPIOINT->IO2IntClr = 1 << bitloc;
+		rise2 -= 1<<bitloc;
+  }
+}
+fall2:
+if (fall2==0)
+	goto end;
+/*if ((fall2 & (fall2 - 1)) == 0) {
+  callbacksP2[fall2]();
+	//LPC_GPIOINT->IO2IntClr = fall2;
+}*/
+else {
+while(fall2 > 0) {
+		bitloc = 31 - __CLZ(fall2);
+		if (callbacksP2[bitloc]!=0)
+			callbacksP2[bitloc]();
+		//LPC_GPIOINT->IO2IntClr = 1 << bitloc;
+		fall2 -= 1<<bitloc;
+}
+end:
+//NVIC_ClearPendingIRQ(EINT3_IRQn);
+//LPC_GPIOINT->IO0IntClr = LPC_GPIOINT->IO2IntClr = 0xFFFFFFFF;
+//NVIC_ClearPendingIRQ(EINT3_IRQn);
+return; //silences warning
+}
+}
+#endif
diff --git a/Marlin/src/HAL/HAL_LPC1768/arduino.h b/Marlin/src/HAL/HAL_LPC1768/arduino.h
index a8a67d5c77..f34e8217ab 100644
--- a/Marlin/src/HAL/HAL_LPC1768/arduino.h
+++ b/Marlin/src/HAL/HAL_LPC1768/arduino.h
@@ -28,6 +28,9 @@
 
 #define LOW          0x00
 #define HIGH         0x01
+#define CHANGE       0x02
+#define FALLING      0x03
+#define RISING       0x04
 
 #define INPUT        0x00
 #define OUTPUT       0x01
@@ -64,6 +67,10 @@ typedef uint8_t byte;
 //Interrupts
 void cli(void); // Disable
 void sei(void); // Enable
+void attachInterrupt(uint32_t pin, void (*callback)(void), uint32_t mode);
+void detachInterrupt(uint32_t pin);
+extern "C" void GpioEnableInt(uint32_t port, uint32_t pin, uint32_t mode);
+extern "C" void GpioDisableInt(uint32_t port, uint32_t pin);
 
 // Program Memory
 #define pgm_read_ptr(address_short) (*(address_short))
diff --git a/Marlin/src/HAL/HAL_LPC1768/pinmap_re_arm.h b/Marlin/src/HAL/HAL_LPC1768/pinmap_re_arm.h
index 65c57ada45..2726fdefee 100644
--- a/Marlin/src/HAL/HAL_LPC1768/pinmap_re_arm.h
+++ b/Marlin/src/HAL/HAL_LPC1768/pinmap_re_arm.h
@@ -95,6 +95,50 @@ const adc_pin_data adc_pin_map[] = {
                        r == 54 ? 1 :\
                        r == 60 ? 1 : 0)
 
+#define NUM_INTERRUPT_PINS 35
+
+#define INTERRUPT_PIN(r)  ( r< 0  ? 0 :\
+                        r == 0  ? 1 :\
+                        r == 1  ? 1 :\
+                        r == 8  ? 1 :\
+                        r == 9  ? 1 :\
+                        r == 10 ? 1 :\
+                        r == 12 ? 1 :\
+                        r == 16 ? 1 :\
+                        r == 20 ? 1 :\
+                        r == 21 ? 1 :\
+                        r == 24 ? 1 :\
+                        r == 25 ? 1 :\
+                        r == 26 ? 1 :\
+                        r == 28 ? 1 :\
+                        r == 34 ? 1 :\
+                        r == 35 ? 1 :\
+                        r == 36 ? 1 :\
+                        r == 38 ? 1 :\
+                        r == 46 ? 1 :\
+                        r == 48 ? 1 :\
+                        r == 50 ? 1 :\
+                        r == 51 ? 1 :\
+                        r == 52 ? 1 :\
+                        r == 54 ? 1 :\
+                        r == 55 ? 1 :\
+                        r == 56 ? 1 :\
+                        r == 57 ? 1 :\
+                        r == 58 ? 1 :\
+                        r == 59 ? 1 :\
+                        r == 60 ? 1 :\
+                        r == 61 ? 1 :\
+                        r == 62 ? 1 :\
+                        r == 63 ? 1 :\
+                        r == 67 ? 1 :\
+                        r == 68 ? 1 :\
+                        r == 69 ? 1 : 0)
+                        /*Internal SD Card */
+                        /*r == 80 ? 1 :\
+                        r == 81 ? 1 :\
+                        r == 82 ? 1 :\
+                        r == 83 ? 1 :\*/
+
 const pin_data pin_map[] = { // pin map for variable pin function
   {0,3},        //  DIO0   RXD0             A6               J4-4                           AUX-1
   {0,2},        //  DIO1   TXD0             A7               J4-5                           AUX-1