diff options
| author | Cristian Maglie <c.maglie@bug.st> | 2012-06-27 13:51:16 +0200 |
|---|---|---|
| committer | Cristian Maglie <c.maglie@bug.st> | 2012-06-27 13:51:16 +0200 |
| commit | a5564b6525c37cb295d05d88963d1ea3c63dd63c (patch) | |
| tree | 613aa68f2c79923d313c6ea4a6cd1fdd9b5c7481 /sam | |
| parent | 4596b23bb844d2bae2a698607073f8f0911cf4ab (diff) | |
| parent | 8ad1900facadb793a33a0fd04d884d8cdf3947d6 (diff) | |
Merged master
Diffstat (limited to 'sam')
| -rw-r--r-- | sam/cores/arduino/Client.h | 26 | ||||
| -rw-r--r-- | sam/cores/arduino/IPAddress.cpp | 56 | ||||
| -rw-r--r-- | sam/cores/arduino/IPAddress.h | 76 | ||||
| -rw-r--r-- | sam/cores/arduino/Print.cpp | 3 | ||||
| -rw-r--r-- | sam/cores/arduino/Print.h | 5 | ||||
| -rw-r--r-- | sam/cores/arduino/Server.h | 9 | ||||
| -rw-r--r-- | sam/cores/arduino/Stream.cpp | 270 | ||||
| -rw-r--r-- | sam/cores/arduino/Stream.h | 63 | ||||
| -rw-r--r-- | sam/cores/arduino/USB/USBAPI.h | 7 | ||||
| -rw-r--r-- | sam/cores/arduino/USB/USBCore.cpp | 12 | ||||
| -rw-r--r-- | sam/cores/arduino/Udp.h | 88 | ||||
| -rw-r--r-- | sam/cores/arduino/main.cpp | 5 | ||||
| -rw-r--r-- | sam/cores/arduino/wiring_analog.c | 90 | ||||
| -rw-r--r-- | sam/cores/arduino/wiring_constants.h | 1 | ||||
| -rw-r--r-- | sam/cores/arduino/wiring_digital.c | 25 | ||||
| -rw-r--r-- | sam/cores/arduino/wiring_shift.c | 4 | ||||
| -rw-r--r-- | sam/platform.txt | 23 |
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 |
