aboutsummaryrefslogtreecommitdiff
path: root/sam
diff options
context:
space:
mode:
authorCristian Maglie <c.maglie@bug.st>2012-06-27 13:51:16 +0200
committerCristian Maglie <c.maglie@bug.st>2012-06-27 13:51:16 +0200
commita5564b6525c37cb295d05d88963d1ea3c63dd63c (patch)
tree613aa68f2c79923d313c6ea4a6cd1fdd9b5c7481 /sam
parent4596b23bb844d2bae2a698607073f8f0911cf4ab (diff)
parent8ad1900facadb793a33a0fd04d884d8cdf3947d6 (diff)
Merged master
Diffstat (limited to 'sam')
-rw-r--r--sam/cores/arduino/Client.h26
-rw-r--r--sam/cores/arduino/IPAddress.cpp56
-rw-r--r--sam/cores/arduino/IPAddress.h76
-rw-r--r--sam/cores/arduino/Print.cpp3
-rw-r--r--sam/cores/arduino/Print.h5
-rw-r--r--sam/cores/arduino/Server.h9
-rw-r--r--sam/cores/arduino/Stream.cpp270
-rw-r--r--sam/cores/arduino/Stream.h63
-rw-r--r--sam/cores/arduino/USB/USBAPI.h7
-rw-r--r--sam/cores/arduino/USB/USBCore.cpp12
-rw-r--r--sam/cores/arduino/Udp.h88
-rw-r--r--sam/cores/arduino/main.cpp5
-rw-r--r--sam/cores/arduino/wiring_analog.c90
-rw-r--r--sam/cores/arduino/wiring_constants.h1
-rw-r--r--sam/cores/arduino/wiring_digital.c25
-rw-r--r--sam/cores/arduino/wiring_shift.c4
-rw-r--r--sam/platform.txt23
17 files changed, 703 insertions, 60 deletions
diff --git a/sam/cores/arduino/Client.h b/sam/cores/arduino/Client.h
new file mode 100644
index 0000000..ea13483
--- /dev/null
+++ b/sam/cores/arduino/Client.h
@@ -0,0 +1,26 @@
+#ifndef client_h
+#define client_h
+#include "Print.h"
+#include "Stream.h"
+#include "IPAddress.h"
+
+class Client : public Stream {
+
+public:
+ virtual int connect(IPAddress ip, uint16_t port) =0;
+ virtual int connect(const char *host, uint16_t port) =0;
+ virtual size_t write(uint8_t) =0;
+ virtual size_t write(const uint8_t *buf, size_t size) =0;
+ virtual int available() = 0;
+ virtual int read() = 0;
+ virtual int read(uint8_t *buf, size_t size) = 0;
+ virtual int peek() = 0;
+ virtual void flush() = 0;
+ virtual void stop() = 0;
+ virtual uint8_t connected() = 0;
+ virtual operator bool() = 0;
+protected:
+ uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); };
+};
+
+#endif
diff --git a/sam/cores/arduino/IPAddress.cpp b/sam/cores/arduino/IPAddress.cpp
new file mode 100644
index 0000000..fe3deb7
--- /dev/null
+++ b/sam/cores/arduino/IPAddress.cpp
@@ -0,0 +1,56 @@
+
+#include <Arduino.h>
+#include <IPAddress.h>
+
+IPAddress::IPAddress()
+{
+ memset(_address, 0, sizeof(_address));
+}
+
+IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet)
+{
+ _address[0] = first_octet;
+ _address[1] = second_octet;
+ _address[2] = third_octet;
+ _address[3] = fourth_octet;
+}
+
+IPAddress::IPAddress(uint32_t address)
+{
+ memcpy(_address, &address, sizeof(_address));
+}
+
+IPAddress::IPAddress(const uint8_t *address)
+{
+ memcpy(_address, address, sizeof(_address));
+}
+
+IPAddress& IPAddress::operator=(const uint8_t *address)
+{
+ memcpy(_address, address, sizeof(_address));
+ return *this;
+}
+
+IPAddress& IPAddress::operator=(uint32_t address)
+{
+ memcpy(_address, (const uint8_t *)&address, sizeof(_address));
+ return *this;
+}
+
+bool IPAddress::operator==(const uint8_t* addr)
+{
+ return memcmp(addr, _address, sizeof(_address)) == 0;
+}
+
+size_t IPAddress::printTo(Print& p) const
+{
+ size_t n = 0;
+ for (int i =0; i < 3; i++)
+ {
+ n += p.print(_address[i], DEC);
+ n += p.print('.');
+ }
+ n += p.print(_address[3], DEC);
+ return n;
+}
+
diff --git a/sam/cores/arduino/IPAddress.h b/sam/cores/arduino/IPAddress.h
new file mode 100644
index 0000000..2585aec
--- /dev/null
+++ b/sam/cores/arduino/IPAddress.h
@@ -0,0 +1,76 @@
+/*
+ *
+ * MIT License:
+ * Copyright (c) 2011 Adrian McEwen
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * adrianm@mcqn.com 1/1/2011
+ */
+
+#ifndef IPAddress_h
+#define IPAddress_h
+
+#include <Printable.h>
+
+// A class to make it easier to handle and pass around IP addresses
+
+class IPAddress : public Printable {
+private:
+ uint8_t _address[4]; // IPv4 address
+ // Access the raw byte array containing the address. Because this returns a pointer
+ // to the internal structure rather than a copy of the address this function should only
+ // be used when you know that the usage of the returned uint8_t* will be transient and not
+ // stored.
+ uint8_t* raw_address() { return _address; };
+
+public:
+ // Constructors
+ IPAddress();
+ IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet);
+ IPAddress(uint32_t address);
+ IPAddress(const uint8_t *address);
+
+ // Overloaded cast operator to allow IPAddress objects to be used where a pointer
+ // to a four-byte uint8_t array is expected
+ operator uint32_t() { return *((uint32_t*)_address); };
+ bool operator==(const IPAddress& addr) { return (*((uint32_t*)_address)) == (*((uint32_t*)addr._address)); };
+ bool operator==(const uint8_t* addr);
+
+ // Overloaded index operator to allow getting and setting individual octets of the address
+ uint8_t operator[](int index) const { return _address[index]; };
+ uint8_t& operator[](int index) { return _address[index]; };
+
+ // Overloaded copy operators to allow initialisation of IPAddress objects from other types
+ IPAddress& operator=(const uint8_t *address);
+ IPAddress& operator=(uint32_t address);
+
+ virtual size_t printTo(Print& p) const;
+
+ friend class EthernetClass;
+ friend class UDP;
+ friend class Client;
+ friend class Server;
+ friend class DhcpClass;
+ friend class DNSClient;
+};
+
+const IPAddress INADDR_NONE(0,0,0,0);
+
+
+#endif
diff --git a/sam/cores/arduino/Print.cpp b/sam/cores/arduino/Print.cpp
index 123370f..4a21176 100644
--- a/sam/cores/arduino/Print.cpp
+++ b/sam/cores/arduino/Print.cpp
@@ -219,6 +219,9 @@ size_t Print::printFloat(double number, uint8_t digits)
{
size_t n = 0;
+ if (isnan(number)) return print("nan");
+ if (isinf(number)) return print("inf");
+
// Handle negative numbers
if (number < 0.0)
{
diff --git a/sam/cores/arduino/Print.h b/sam/cores/arduino/Print.h
index 1af6b72..dc76150 100644
--- a/sam/cores/arduino/Print.h
+++ b/sam/cores/arduino/Print.h
@@ -46,7 +46,10 @@ class Print
void clearWriteError() { setWriteError(0); }
virtual size_t write(uint8_t) = 0;
- size_t write(const char *str) { return write((const uint8_t *)str, strlen(str)); }
+ size_t write(const char *str) {
+ if (str == NULL) return 0;
+ return write((const uint8_t *)str, strlen(str));
+ }
virtual size_t write(const uint8_t *buffer, size_t size);
size_t print(const __FlashStringHelper *);
diff --git a/sam/cores/arduino/Server.h b/sam/cores/arduino/Server.h
new file mode 100644
index 0000000..9674c76
--- /dev/null
+++ b/sam/cores/arduino/Server.h
@@ -0,0 +1,9 @@
+#ifndef server_h
+#define server_h
+
+class Server : public Print {
+public:
+ virtual void begin() =0;
+};
+
+#endif
diff --git a/sam/cores/arduino/Stream.cpp b/sam/cores/arduino/Stream.cpp
new file mode 100644
index 0000000..aafb7fc
--- /dev/null
+++ b/sam/cores/arduino/Stream.cpp
@@ -0,0 +1,270 @@
+/*
+ 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
+ */
+
+#include "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, NULL);
+}
+
+// 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)
+{
+ size_t index = 0; // maximum target string length is 64k bytes!
+ size_t termIndex = 0;
+ int c;
+
+ if( *target == 0)
+ return true; // return true if target is a null string
+ while( (c = timedRead()) > 0){
+
+ if(c != target[index])
+ index = 0; // reset index if any char does not match
+
+ if( c == target[index]){
+ //////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
+ if(++index >= targetLen){ // return true if all chars in the target match
+ return true;
+ }
+ }
+
+ if(termLen > 0 && c == terminator[termIndex]){
+ if(++termIndex >= termLen)
+ return false; // return false if terminate string found before target string
+ }
+ else
+ termIndex = 0;
+ }
+ return 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)
+{
+ boolean 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){
+ boolean isNegative = false;
+ boolean 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;
+}
+
diff --git a/sam/cores/arduino/Stream.h b/sam/cores/arduino/Stream.h
index aaa189f..58bbf75 100644
--- a/sam/cores/arduino/Stream.h
+++ b/sam/cores/arduino/Stream.h
@@ -15,21 +15,82 @@
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"
+// 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
{
+ private:
+ 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
+ // 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
+ // returns true if target string is found, false if timed out
+
+ bool findUntil(char *target, char *terminator); // as find but search ends if the terminator string is found
+
+ bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found
+
+
+ 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
+ // 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
+ // 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
};
#endif
diff --git a/sam/cores/arduino/USB/USBAPI.h b/sam/cores/arduino/USB/USBAPI.h
index 592d3a0..de98895 100644
--- a/sam/cores/arduino/USB/USBAPI.h
+++ b/sam/cores/arduino/USB/USBAPI.h
@@ -27,17 +27,17 @@
//================================================================================
// USB
-class USB_
+class USBDevice_
{
public:
- USB_();
+ USBDevice_();
bool configured();
bool attach();
bool detach(); // Serial port goes down too...
void poll();
};
-extern USB_ USB;
+extern USBDevice_ USBDevice;
//================================================================================
//================================================================================
@@ -57,6 +57,7 @@ public:
virtual int read(void);
virtual void flush(void);
virtual size_t write(uint8_t);
+ using Print::write; // pull in write(str) and write(buf, size) from Print
operator bool();
};
extern Serial_ Serial;
diff --git a/sam/cores/arduino/USB/USBCore.cpp b/sam/cores/arduino/USB/USBCore.cpp
index 77eaee1..3b4a2ce 100644
--- a/sam/cores/arduino/USB/USBCore.cpp
+++ b/sam/cores/arduino/USB/USBCore.cpp
@@ -536,9 +536,9 @@ uint32_t USBD_Connected(void)
//=======================================================================
//=======================================================================
-USB_ USB;
+USBDevice_ USBDevice;
-USB_::USB_()
+USBDevice_::USBDevice_()
{
UDD_SetStack(&USB_ISR);
@@ -548,7 +548,7 @@ USB_::USB_()
}
}
-bool USB_::attach(void)
+bool USBDevice_::attach(void)
{
if (_usbInitialized != 0UL)
{
@@ -562,7 +562,7 @@ bool USB_::attach(void)
}
}
-bool USB_::detach(void)
+bool USBDevice_::detach(void)
{
if (_usbInitialized != 0UL)
{
@@ -577,11 +577,11 @@ bool USB_::detach(void)
// Check for interrupts
// TODO: VBUS detection
-bool USB_::configured()
+bool USBDevice_::configured()
{
return _usbConfiguration;
}
-void USB_::poll()
+void USBDevice_::poll()
{
}
diff --git a/sam/cores/arduino/Udp.h b/sam/cores/arduino/Udp.h
new file mode 100644
index 0000000..dc5644b
--- /dev/null
+++ b/sam/cores/arduino/Udp.h
@@ -0,0 +1,88 @@
+/*
+ * Udp.cpp: Library to send/receive UDP packets.
+ *
+ * NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these)
+ * 1) UDP does not guarantee the order in which assembled UDP packets are received. This
+ * might not happen often in practice, but in larger network topologies, a UDP
+ * packet can be received out of sequence.
+ * 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being
+ * aware of it. Again, this may not be a concern in practice on small local networks.
+ * For more information, see http://www.cafeaulait.org/course/week12/35.html
+ *
+ * MIT License:
+ * Copyright (c) 2008 Bjoern Hartmann
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * bjoern@cs.stanford.edu 12/30/2008
+ */
+
+#ifndef udp_h
+#define udp_h
+
+#include <Stream.h>
+#include <IPAddress.h>
+
+class UDP : public Stream {
+
+public:
+ virtual uint8_t begin(uint16_t) =0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
+ virtual void stop() =0; // Finish with the UDP socket
+
+ // Sending UDP packets
+
+ // Start building up a packet to send to the remote host specific in ip and port
+ // Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
+ virtual int beginPacket(IPAddress ip, uint16_t port) =0;
+ // Start building up a packet to send to the remote host specific in host and port
+ // Returns 1 if successful, 0 if there was a problem resolving the hostname or port
+ virtual int beginPacket(const char *host, uint16_t port) =0;
+ // Finish off this packet and send it
+ // Returns 1 if the packet was sent successfully, 0 if there was an error
+ virtual int endPacket() =0;
+ // Write a single byte into the packet
+ virtual size_t write(uint8_t) =0;
+ // Write size bytes from buffer into the packet
+ virtual size_t write(const uint8_t *buffer, size_t size) =0;
+
+ // Start processing the next available incoming packet
+ // Returns the size of the packet in bytes, or 0 if no packets are available
+ virtual int parsePacket() =0;
+ // Number of bytes remaining in the current packet
+ virtual int available() =0;
+ // Read a single byte from the current packet
+ virtual int read() =0;
+ // Read up to len bytes from the current packet and place them into buffer
+ // Returns the number of bytes read, or 0 if none are available
+ virtual int read(unsigned char* buffer, size_t len) =0;
+ // Read up to len characters from the current packet and place them into buffer
+ // Returns the number of characters read, or 0 if none are available
+ virtual int read(char* buffer, size_t len) =0;
+ // Return the next byte from the current packet without moving on to the next byte
+ virtual int peek() =0;
+ virtual void flush() =0; // Finish reading the current packet
+
+ // Return the IP address of the host who sent the current incoming packet
+ virtual IPAddress remoteIP() =0;
+ // Return the port of the host who sent the current incoming packet
+ virtual uint16_t remotePort() =0;
+protected:
+ uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); };
+};
+
+#endif
diff --git a/sam/cores/arduino/main.cpp b/sam/cores/arduino/main.cpp
index 69f25f2..f28b6fd 100644
--- a/sam/cores/arduino/main.cpp
+++ b/sam/cores/arduino/main.cpp
@@ -39,13 +39,16 @@ int main( void )
delay(1);
- USB.attach();
+#if defined(USBCON)
+ USBDevice.attach();
+#endif
setup();
for (;;)
{
loop();
+ if (serialEventRun) serialEventRun();
}
return 0;
diff --git a/sam/cores/arduino/wiring_analog.c b/sam/cores/arduino/wiring_analog.c
index 0cdc789..d5bf6dd 100644
--- a/sam/cores/arduino/wiring_analog.c
+++ b/sam/cores/arduino/wiring_analog.c
@@ -91,7 +91,7 @@ uint32_t analogRead(uint32_t ulPin)
;
// Read the value
- ulValue = adc12b_get_latest_value(ADC12B);
+ ulValue = adc12b_get_latest_value(ADC12B) >> 2;
// Stop the ADC12B
// adc12_stop( ADC12B ) ; // never do adc12_stop() else we have to reconfigure the ADC12B each time
@@ -135,7 +135,7 @@ uint32_t analogRead(uint32_t ulPin)
;
// Read the value
- ulValue = adc_get_latest_value(ADC);
+ ulValue = adc_get_latest_value(ADC) >> 2;
// Disable the corresponding channel
adc_disable_channel(ADC, ulChannel);
@@ -151,24 +151,34 @@ uint32_t analogRead(uint32_t ulPin)
return ulValue;
}
-static void TC_SetRA(Tc *tc, uint32_t chan, uint32_t v )
+static void TC_SetRA(Tc *tc, uint32_t chan, uint32_t v)
{
tc->TC_CHANNEL[chan].TC_RA = v;
}
-static void TC_SetRB(Tc *tc, uint32_t chan, uint32_t v )
+static void TC_SetRB(Tc *tc, uint32_t chan, uint32_t v)
{
tc->TC_CHANNEL[chan].TC_RB = v;
}
-static void TC_SetRC(Tc *tc, uint32_t chan, uint32_t v )
+static void TC_SetRC(Tc *tc, uint32_t chan, uint32_t v)
{
tc->TC_CHANNEL[chan].TC_RC = v;
}
+static void TC_SetCMR_ChannelA(Tc *tc, uint32_t chan, uint32_t v)
+{
+ tc->TC_CHANNEL[chan].TC_CMR = (tc->TC_CHANNEL[chan].TC_CMR & 0xFFF0FFFF) | v;
+}
+
+static void TC_SetCMR_ChannelB(Tc *tc, uint32_t chan, uint32_t v)
+{
+ tc->TC_CHANNEL[chan].TC_CMR = (tc->TC_CHANNEL[chan].TC_CMR & 0xF0FFFFFF) | v;
+}
+
static uint8_t PWMEnabled = 0;
static uint8_t pinEnabled[PINS_COUNT];
-static uint8_t TCChanEnabled[] = {0, 0, 0};
+static uint8_t TCChanEnabled[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
void analogOutputInit(void) {
uint8_t i;
@@ -254,38 +264,52 @@ void analogWrite(uint32_t ulPin, uint32_t ulValue) {
}
if ((attr & PIN_ATTR_TIMER) == PIN_ATTR_TIMER) {
- // We use MCLK/2 => 96Mhz/2 => 48Mhz as clock.
- // To get 1KHz we should use 48000 as TC
- // 48Mhz/48000 = 1KHz
+ // We use MCLK/2 as clock.
const uint32_t TC = VARIANT_MCK / 2 / TC_FREQUENCY;
- // Map value to Timer ranges 0..255=>0..48000
+ // Map value to Timer ranges 0..255 => 0..TC
ulValue = ulValue * TC;
ulValue = ulValue / TC_MAX_DUTY_CYCLE;
// Setup Timer for this pin
ETCChannel channel = g_APinDescription[ulPin].ulTCChannel;
- static const uint32_t channelToChNo[] = { 0, 0, 1, 1, 2, 2 };
- static const uint32_t channelToAB[] = { 1, 0, 1, 0, 1, 0 };
+ static const uint32_t channelToChNo[] = { 0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2 };
+ static const uint32_t channelToAB[] = { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 };
+ static const Tc *channelToTC[] = {
+ TC0, TC0, TC0, TC0, TC0, TC0,
+ TC1, TC1, TC1, TC1, TC1, TC1,
+ TC2, TC2, TC2, TC2, TC2, TC2 };
+ static const uint32_t channelToId[] = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8 };
uint32_t chNo = channelToChNo[channel];
- uint32_t chA = channelToAB[channel];
-
- if (!TCChanEnabled[chNo]) {
- pmc_enable_periph_clk(TC_INTERFACE_ID + chNo);
- TC_Configure(TC_INTERFACE, chNo,
- TC_CMR_TCCLKS_TIMER_CLOCK1 |
- TC_CMR_WAVE |
- TC_CMR_WAVSEL_UP_RC |
- TC_CMR_ACPA_CLEAR | // RA Compare Effect on OA: clear
- TC_CMR_ACPC_SET | // RC Compare Effect on OA: set
- TC_CMR_BCPB_CLEAR | // RB Compare Effect on OB: clear
- TC_CMR_BCPC_SET); // RC Compare Effect on OB: set
- TC_SetRC(TC_INTERFACE, chNo, TC);
+ uint32_t chA = channelToAB[channel];
+ Tc *chTC = channelToTC[channel];
+ uint32_t interfaceID = channelToId[channel];
+
+ if (!TCChanEnabled[interfaceID]) {
+ pmc_enable_periph_clk(TC_INTERFACE_ID + interfaceID);
+ TC_Configure(chTC, chNo,
+ TC_CMR_TCCLKS_TIMER_CLOCK1 |
+ TC_CMR_WAVE | // Waveform mode
+ TC_CMR_WAVSEL_UP_RC | // Counter running up and reset when equals to RC
+ TC_CMR_EEVT_XC0 | // Set external events from XC0 (this setup TIOB as output)
+ TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_CLEAR |
+ TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_CLEAR);
+ TC_SetRC(chTC, chNo, TC);
+ }
+ if (ulValue == 0) {
+ if (chA)
+ TC_SetCMR_ChannelA(chTC, chNo, TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_CLEAR);
+ else
+ TC_SetCMR_ChannelB(chTC, chNo, TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_CLEAR);
+ } else {
+ if (chA) {
+ TC_SetRA(chTC, chNo, ulValue);
+ TC_SetCMR_ChannelA(chTC, chNo, TC_CMR_ACPA_CLEAR | TC_CMR_ACPC_SET);
+ } else {
+ TC_SetRB(chTC, chNo, ulValue);
+ TC_SetCMR_ChannelB(chTC, chNo, TC_CMR_BCPB_CLEAR | TC_CMR_BCPC_SET);
+ }
}
- if (chA)
- TC_SetRA(TC_INTERFACE, chNo, ulValue);
- else
- TC_SetRB(TC_INTERFACE, chNo, ulValue);
if (!pinEnabled[ulPin]) {
PIO_Configure(g_APinDescription[ulPin].pPort,
g_APinDescription[ulPin].ulPinType,
@@ -293,14 +317,14 @@ void analogWrite(uint32_t ulPin, uint32_t ulValue) {
g_APinDescription[ulPin].ulPinConfiguration);
pinEnabled[ulPin] = 1;
}
- if (!TCChanEnabled[chNo]) {
- TC_Start(TC_INTERFACE, chNo);
- TCChanEnabled[chNo] = 1;
+ if (!TCChanEnabled[interfaceID]) {
+ TC_Start(chTC, chNo);
+ TCChanEnabled[interfaceID] = 1;
}
return;
}
- // Default to digital write
+ // Defaults to digital write
pinMode(ulPin, OUTPUT);
if (ulValue < 128)
digitalWrite(ulPin, LOW);
diff --git a/sam/cores/arduino/wiring_constants.h b/sam/cores/arduino/wiring_constants.h
index 0555d71..868d46d 100644
--- a/sam/cores/arduino/wiring_constants.h
+++ b/sam/cores/arduino/wiring_constants.h
@@ -28,6 +28,7 @@ extern "C"{
#define INPUT 0x0
#define OUTPUT 0x1
+#define INPUT_PULLUP 0x2
#define true 0x1
#define false 0x0
diff --git a/sam/cores/arduino/wiring_digital.c b/sam/cores/arduino/wiring_digital.c
index bbd940d..ac6eb18 100644
--- a/sam/cores/arduino/wiring_digital.c
+++ b/sam/cores/arduino/wiring_digital.c
@@ -34,16 +34,35 @@ extern void pinMode( uint32_t ulPin, uint32_t ulMode )
case INPUT:
/* Enable peripheral for clocking input */
pmc_enable_periph_clk( g_APinDescription[ulPin].ulPeripheralId ) ;
- PIO_Configure( g_APinDescription[ulPin].pPort, PIO_INPUT, g_APinDescription[ulPin].ulPin, 0 ) ;
+ PIO_Configure(
+ g_APinDescription[ulPin].pPort,
+ PIO_INPUT,
+ g_APinDescription[ulPin].ulPin,
+ 0 ) ;
+ break ;
+
+ case INPUT_PULLUP:
+ /* Enable peripheral for clocking input */
+ pmc_enable_periph_clk( g_APinDescription[ulPin].ulPeripheralId ) ;
+ PIO_Configure(
+ g_APinDescription[ulPin].pPort,
+ PIO_INPUT,
+ g_APinDescription[ulPin].ulPin,
+ PIO_PULLUP ) ;
break ;
case OUTPUT:
- /* if all pins are output, disable PIO Controller clocking, reduce power consomption */
+ PIO_Configure(
+ g_APinDescription[ulPin].pPort,
+ PIO_OUTPUT_1,
+ g_APinDescription[ulPin].ulPin,
+ g_APinDescription[ulPin].ulPinConfiguration ) ;
+
+ /* if all pins are output, disable PIO Controller clocking, reduce power consumption */
if ( g_APinDescription[ulPin].pPort->PIO_OSR == 0xffffffff )
{
pmc_disable_periph_clk( g_APinDescription[ulPin].ulPeripheralId ) ;
}
- PIO_Configure( g_APinDescription[ulPin].pPort, PIO_OUTPUT_1, g_APinDescription[ulPin].ulPin, g_APinDescription[ulPin].ulPinConfiguration ) ;
break ;
default:
diff --git a/sam/cores/arduino/wiring_shift.c b/sam/cores/arduino/wiring_shift.c
index 30d3f43..302f0b5 100644
--- a/sam/cores/arduino/wiring_shift.c
+++ b/sam/cores/arduino/wiring_shift.c
@@ -22,7 +22,7 @@
extern "C"{
#endif
-extern uint32_t shiftIn( uint32_t ulDataPin, uint32_t ulClockPin, uint32_t ulBitOrder )
+uint32_t shiftIn( uint32_t ulDataPin, uint32_t ulClockPin, uint32_t ulBitOrder )
{
uint8_t value = 0 ;
uint8_t i ;
@@ -46,7 +46,7 @@ extern uint32_t shiftIn( uint32_t ulDataPin, uint32_t ulClockPin, uint32_t ulBit
return value ;
}
-extern void shiftOut( uint32_t ulDataPin, uint32_t ulClockPin, uint32_t ulBitOrder, uint32_t ulVal )
+void shiftOut( uint32_t ulDataPin, uint32_t ulClockPin, uint32_t ulBitOrder, uint32_t ulVal )
{
uint8_t i ;
diff --git a/sam/platform.txt b/sam/platform.txt
index e928040..17c4344 100644
--- a/sam/platform.txt
+++ b/sam/platform.txt
@@ -6,12 +6,12 @@ name=Atmel SAM3
compiler.path={runtime.ide.path}/hardware/tools/g++_arm_none_eabi/bin/
#compiler.path=C:/arm-none-eabi-gcc-4_6/bin/
compiler.c.cmd=arm-none-eabi-gcc
-compiler.c.flags=-c -g -Os -w -mlong-calls -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -Dprintf=iprintf
+compiler.c.flags=-c -g -Os -w -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -Dprintf=iprintf
compiler.c.elf.cmd=arm-none-eabi-gcc
compiler.c.elf.flags=-Os -Wl,--gc-sections
compiler.S.flags=-c -g -assembler-with-cpp
compiler.cpp.cmd=arm-none-eabi-g++
-compiler.cpp.flags=-c -g -Os -w -mlong-calls -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -Dprintf=iprintf
+compiler.cpp.flags=-c -g -Os -w -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -Dprintf=iprintf
compiler.ar.cmd=arm-none-eabi-ar
compiler.ar.flags=rcs
compiler.objcopy.cmd=arm-none-eabi-objcopy
@@ -21,32 +21,35 @@ compiler.elf2hex.cmd=arm-none-eabi-objcopy
compiler.ldflags=
compiler.size.cmd=arm-none-eabi-size
compiler.define=-DARDUINO=
+# this can be overriden in boards.txt
+build.extra_flags=
-compiler.libsam.c.flags=-I{build.system.path}/libsam -I{build.system.path}/CMSIS/CMSIS/Include/ -I{build.system.path}/CMSIS/Device/ATMEL/
+
+compiler.libsam.c.flags="-I{build.system.path}/libsam" "-I{build.system.path}/CMSIS/CMSIS/Include/" "-I{build.system.path}/CMSIS/Device/ATMEL/"
# SAM3 compile patterns
# ---------------------
## Compile c files
-recipe.c.o.pattern={compiler.path}{compiler.c.cmd} {compiler.c.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -D{software}={runtime.ide.version} {build.extra_flags} {compiler.libsam.c.flags} {includes} {source_file} -o {object_file}
+recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -D{software}={runtime.ide.version} {build.extra_flags} {compiler.libsam.c.flags} {includes} "{source_file}" -o "{object_file}"
## Compile c++ files
-recipe.cpp.o.pattern={compiler.path}{compiler.cpp.cmd} {compiler.cpp.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -D{software}={runtime.ide.version} {build.extra_flags} {compiler.libsam.c.flags} {includes} {source_file} -o {object_file}
+recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -D{software}={runtime.ide.version} {build.extra_flags} {compiler.libsam.c.flags} {includes} "{source_file}" -o "{object_file}"
## Create archives
-recipe.ar.pattern={compiler.path}{compiler.ar.cmd} {compiler.ar.flags} {build.path}/{archive_file} {object_file}
+recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} "{build.path}/{archive_file}" "{object_file}"
## Combine gc-sections, archives, and objects
-recipe.c.combine.pattern={compiler.path}{compiler.c.elf.cmd} {compiler.c.elf.flags} -mcpu={build.mcu} -T{build.variant.path}/{build.ldscript} -Wl,-Map,{build.path}/{build.project_name}.map -o {build.path}/{build.project_name}.elf -L{build.path} -lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group {object_files} {build.variant.path}/{build.variant_system_lib} {build.path}/{archive_file} -Wl,--end-group
+recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mcpu={build.mcu} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" -o "{build.path}/{build.project_name}.elf" "-L{build.path}" -lm -lgcc -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group "{build.path}/syscalls_sam3.c.o" {object_files} "{build.variant.path}/{build.variant_system_lib}" "{build.path}/{archive_file}" -Wl,--end-group
## Create eeprom
recipe.objcopy.eep.pattern=
## Create hex
-recipe.objcopy.hex.pattern={compiler.path}{compiler.elf2hex.cmd} {compiler.elf2hex.flags} {build.path}/{build.project_name}.elf {build.path}/{build.project_name}.bin
+recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.bin"
## Compute size
-recipe.size.pattern={compiler.path}{compiler.size.cmd} -A {build.path}/{build.project_name}.elf
+recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf"
recipe.size.regex=\.text\s+([0-9]+).*
@@ -59,7 +62,7 @@ tools.bossac.path={runtime.ide.path}/hardware/tools
tools.bossac.upload.params.verbose=-i -d
tools.bossac.upload.params.quiet=
-tools.bossac.upload.pattern={path}/{cmd} {upload.verbose} --port={serial.port.file} -e -w -v -b {build.path}/{build.project_name}.bin
+tools.bossac.upload.pattern="{path}/{cmd}" {upload.verbose} --port={serial.port.file} -e -w -v -b "{build.path}/{build.project_name}.bin"
# specialized tool for adk2 to twiddle the erase line before running bossac
tools.adk2install.cmd=adk2install