Browse Source

add HardwareSerial and SoftwareSerial for Re-ARM.

HardwareSerial has been tested on Uart0 (debug header) and Uart3 (i2c connector)
Software Serial has been tested to work bi-directionally at 9600 and 115200
using pins 6 and 63 on J5, and unidirectionally (write only) at 250000.
The code used to test was Teemuatlut's tmc2208 patch, and a few small changes to main used to echo recieved chars back to a host pc.
pull/1/head
kfazz 7 years ago
committed by Scott Lahteine
parent
commit
18f97c4013
  1. 5
      Marlin/frameworks/CMSIS/LPC1768/lib/Print.cpp
  2. 319
      Marlin/frameworks/CMSIS/LPC1768/lib/Stream.cpp
  3. 117
      Marlin/frameworks/CMSIS/LPC1768/lib/Stream.h
  4. 229
      Marlin/frameworks/CMSIS/LPC1768/lib/WString.h
  5. 636
      Marlin/src/HAL/HAL_LPC1768/HardwareSerial.cpp
  6. 149
      Marlin/src/HAL/HAL_LPC1768/HardwareSerial.h
  7. 398
      Marlin/src/HAL/HAL_LPC1768/SoftwareSerial.cpp
  8. 119
      Marlin/src/HAL/HAL_LPC1768/SoftwareSerial.h
  9. 224
      Marlin/src/HAL/HAL_LPC1768/WInterrupts.cpp
  10. 7
      Marlin/src/HAL/HAL_LPC1768/arduino.h
  11. 44
      Marlin/src/HAL/HAL_LPC1768/pinmap_re_arm.h

5
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 */

319
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;
}

117
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

229
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

636
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

149
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_ */

398
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];
}

119
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

224
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

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

44
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

Loading…
Cancel
Save