diff options
Diffstat (limited to 'cores')
| -rw-r--r-- | cores/arduino/CDC.cpp | 79 | ||||
| -rw-r--r-- | cores/arduino/HardwareSerial.cpp | 3 | ||||
| -rw-r--r-- | cores/arduino/HardwareSerial.h | 4 | ||||
| -rw-r--r-- | cores/arduino/IPAddress.cpp | 42 | ||||
| -rw-r--r-- | cores/arduino/IPAddress.h | 7 | ||||
| -rw-r--r-- | cores/arduino/PluggableUSB.cpp | 103 | ||||
| -rw-r--r-- | cores/arduino/PluggableUSB.h | 63 | ||||
| -rw-r--r-- | cores/arduino/Print.cpp | 7 | ||||
| -rw-r--r-- | cores/arduino/Stream.cpp | 66 | ||||
| -rw-r--r-- | cores/arduino/Stream.h | 42 | ||||
| -rw-r--r-- | cores/arduino/Tone.cpp | 3 | ||||
| -rw-r--r-- | cores/arduino/USBAPI.h | 64 | ||||
| -rw-r--r-- | cores/arduino/USBCore.cpp | 89 | ||||
| -rw-r--r-- | cores/arduino/USBCore.h | 12 | ||||
| -rw-r--r-- | cores/arduino/USBDesc.h | 47 | ||||
| -rw-r--r-- | cores/arduino/WInterrupts.c | 62 | ||||
| -rw-r--r-- | cores/arduino/wiring.c | 10 | ||||
| -rw-r--r-- | cores/arduino/wiring_digital.c | 2 | ||||
| -rw-r--r-- | cores/arduino/wiring_private.h | 3 | ||||
| -rw-r--r-- | cores/arduino/wiring_pulse.c | 17 | 
20 files changed, 495 insertions, 230 deletions
diff --git a/cores/arduino/CDC.cpp b/cores/arduino/CDC.cpp index d694a2d..f19b44c 100644 --- a/cores/arduino/CDC.cpp +++ b/cores/arduino/CDC.cpp @@ -18,6 +18,7 @@  #include "USBAPI.h"  #include <avr/wdt.h> +#include <util/atomic.h>  #if defined(USBCON) @@ -31,6 +32,7 @@ typedef struct  } LineInfo;  static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 }; +static volatile int32_t breakValue = -1;  #define WEAK __attribute__ ((weak)) @@ -49,8 +51,8 @@ const CDCDescriptor _cdcInterface =  	//	CDC data interface  	D_INTERFACE(CDC_DATA_INTERFACE,2,CDC_DATA_INTERFACE_CLASS,0,0), -	D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,0x40,0), -	D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,0x40,0) +	D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,USB_EP_SIZE,0), +	D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,USB_EP_SIZE,0)  };  int CDC_GetInterface(u8* interfaceNum) @@ -75,6 +77,11 @@ bool CDC_Setup(USBSetup& setup)  	if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)  	{ +		if (CDC_SEND_BREAK == r) +		{ +			breakValue = ((uint16_t)setup.wValueH << 8) | setup.wValueL; +		} +  		if (CDC_SET_LINE_CODING == r)  		{  			USB_RecvControl((void*)&_usbLineInfo,7); @@ -92,11 +99,24 @@ bool CDC_Setup(USBSetup& setup)  			// with a relatively long period so it can finish housekeeping tasks  			// like servicing endpoints before the sketch ends +#ifndef MAGIC_KEY +#define MAGIC_KEY 0x7777 +#endif +#ifndef MAGIC_KEY_POS +#define MAGIC_KEY_POS 0x0800 +#endif +  			// We check DTR state to determine if host port is open (bit 0 of lineState).  			if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0)  			{ -				*(uint16_t *)(RAMEND-1) = *(uint16_t *)0x0800; -				*(uint16_t *)0x0800 = 0x7777; +#if MAGIC_KEY_POS != (RAMEND-1) +				*(uint16_t *)(RAMEND-1) = *(uint16_t *)MAGIC_KEY_POS; +				*(uint16_t *)MAGIC_KEY_POS = MAGIC_KEY; +#else +				// for future boards save the key in the inproblematic RAMEND +				// which is reserved for the main() return value (which will never return) +				*(uint16_t *)MAGIC_KEY_POS = MAGIC_KEY; +#endif  				wdt_enable(WDTO_120MS);  			}  			else @@ -108,7 +128,11 @@ bool CDC_Setup(USBSetup& setup)  				wdt_disable();  				wdt_reset(); -				*(uint16_t *)0x0800 = *(uint16_t *)(RAMEND-1); +#if MAGIC_KEY_POS != (RAMEND-1) +				*(uint16_t *)MAGIC_KEY_POS = *(uint16_t *)(RAMEND-1); +#else +				*(uint16_t *)MAGIC_KEY_POS = 0x0000; +#endif  			}  		}  		return true; @@ -156,6 +180,11 @@ int Serial_::read(void)  	return USB_Recv(CDC_RX);  } +int Serial_::availableForWrite(void) +{ +	return USB_SendSpace(CDC_TX); +} +  void Serial_::flush(void)  {  	USB_Flush(CDC_TX); @@ -205,6 +234,46 @@ Serial_::operator bool() {  	return result;  } +unsigned long Serial_::baud() { +	// Disable interrupts while reading a multi-byte value +	uint32_t baudrate; +	ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { +		baudrate =  _usbLineInfo.dwDTERate; +	} +	return baudrate; +} + +uint8_t Serial_::stopbits() { +	return _usbLineInfo.bCharFormat; +} + +uint8_t Serial_::paritytype() { +	return _usbLineInfo.bParityType; +} + +uint8_t Serial_::numbits() { +	return _usbLineInfo.bDataBits; +} + +bool Serial_::dtr() { +	return _usbLineInfo.lineState & 0x1; +} + +bool Serial_::rts() { +	return _usbLineInfo.lineState & 0x2; +} + +int32_t Serial_::readBreak() { +	int32_t ret; +	// Disable IRQs while reading and clearing breakValue to make +	// sure we don't overwrite a value just set by the ISR. +	ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { +		ret = breakValue; +		breakValue = -1; +	} +	return ret; +} +  Serial_ Serial;  #endif /* if defined(USBCON) */ diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index a2029a8..5cd89e5 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -138,8 +138,7 @@ void HardwareSerial::begin(unsigned long baud, byte config)  void HardwareSerial::end()  {    // wait for transmission of outgoing data -  while (_tx_buffer_head != _tx_buffer_tail) -    ; +  flush();    cbi(*_ucsrb, RXEN0);    cbi(*_ucsrb, TXEN0); diff --git a/cores/arduino/HardwareSerial.h b/cores/arduino/HardwareSerial.h index 1beafc5..8a5bf95 100644 --- a/cores/arduino/HardwareSerial.h +++ b/cores/arduino/HardwareSerial.h @@ -40,14 +40,14 @@  // often work, but occasionally a race condition can occur that makes  // Serial behave erratically. See https://github.com/arduino/Arduino/issues/2405  #if !defined(SERIAL_TX_BUFFER_SIZE) -#if (RAMEND < 1000) +#if ((RAMEND - RAMSTART) < 1023)  #define SERIAL_TX_BUFFER_SIZE 16  #else  #define SERIAL_TX_BUFFER_SIZE 64  #endif  #endif  #if !defined(SERIAL_RX_BUFFER_SIZE) -#if (RAMEND < 1000) +#if ((RAMEND - RAMSTART) < 1023)  #define SERIAL_RX_BUFFER_SIZE 16  #else  #define SERIAL_RX_BUFFER_SIZE 64 diff --git a/cores/arduino/IPAddress.cpp b/cores/arduino/IPAddress.cpp index 899cbd4..76aefa8 100644 --- a/cores/arduino/IPAddress.cpp +++ b/cores/arduino/IPAddress.cpp @@ -43,6 +43,48 @@ IPAddress::IPAddress(const uint8_t *address)      memcpy(_address.bytes, address, sizeof(_address.bytes));  } +bool IPAddress::fromString(const char *address) +{ +    // TODO: add support for "a", "a.b", "a.b.c" formats + +    uint16_t acc = 0; // Accumulator +    uint8_t dots = 0; + +    while (*address) +    { +        char c = *address++; +        if (c >= '0' && c <= '9') +        { +            acc = acc * 10 + (c - '0'); +            if (acc > 255) { +                // Value out of [0..255] range +                return false; +            } +        } +        else if (c == '.') +        { +            if (dots == 3) { +                // Too much dots (there must be 3 dots) +                return false; +            } +            _address.bytes[dots++] = acc; +            acc = 0; +        } +        else +        { +            // Invalid char +            return false; +        } +    } + +    if (dots != 3) { +        // Too few dots (there must be 3 dots) +        return false; +    } +    _address.bytes[3] = acc; +    return true; +} +  IPAddress& IPAddress::operator=(const uint8_t *address)  {      memcpy(_address.bytes, address, sizeof(_address.bytes)); diff --git a/cores/arduino/IPAddress.h b/cores/arduino/IPAddress.h index 94acdc4..d762f2c 100644 --- a/cores/arduino/IPAddress.h +++ b/cores/arduino/IPAddress.h @@ -21,7 +21,8 @@  #define IPAddress_h  #include <stdint.h> -#include <Printable.h> +#include "Printable.h" +#include "WString.h"  // A class to make it easier to handle and pass around IP addresses @@ -45,6 +46,9 @@ public:      IPAddress(uint32_t address);      IPAddress(const uint8_t *address); +    bool fromString(const char *address); +    bool fromString(const String &address) { return fromString(address.c_str()); } +      // 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() const { return _address.dword; }; @@ -71,5 +75,4 @@ public:  const IPAddress INADDR_NONE(0,0,0,0); -  #endif diff --git a/cores/arduino/PluggableUSB.cpp b/cores/arduino/PluggableUSB.cpp index 857a27f..c489d9f 100644 --- a/cores/arduino/PluggableUSB.cpp +++ b/cores/arduino/PluggableUSB.cpp @@ -23,78 +23,93 @@  #if defined(USBCON)	  #ifdef PLUGGABLE_USB_ENABLED -#define MAX_MODULES	6 +extern uint8_t _initEndpoints[]; -static u8 lastIf = CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT; -static u8 lastEp = CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT; - -extern u8 _initEndpoints[]; - -//PUSBCallbacks cbs[MAX_MODULES]; -static u8 modules_count = 0; - -static PUSBListNode* rootNode = NULL; +int PluggableUSB_::getInterface(uint8_t* interfaceCount) +{ +	int sent = 0; +	PluggableUSBModule* node; +	for (node = rootNode; node; node = node->next) { +		int res = node->getInterface(interfaceCount); +		if (res < 0) +			return -1; +		sent += res; +	} +	return sent; +} -int PUSB_GetInterface(u8* interfaceNum) +int PluggableUSB_::getDescriptor(USBSetup& setup)  { -	int ret = 0; -	PUSBListNode* node = rootNode; -	for (u8 i=0; i<modules_count; i++) { -		ret = node->cb->getInterface(interfaceNum); -		node = node->next; +	PluggableUSBModule* node; +	for (node = rootNode; node; node = node->next) { +		int ret = node->getDescriptor(setup); +		// ret!=0 -> request has been processed +		if (ret) +			return ret;  	} -	return ret; +	return 0;  } -int PUSB_GetDescriptor(int8_t t) +void PluggableUSB_::getShortName(char *iSerialNum)  { -	int ret = 0; -	PUSBListNode* node = rootNode; -	for (u8 i=0; i<modules_count && ret == 0; i++) { -		ret = node->cb->getDescriptor(t); -		node = node->next; +	PluggableUSBModule* node; +	for (node = rootNode; node; node = node->next) { +		iSerialNum += node->getShortName(iSerialNum);  	} -	return ret; +	*iSerialNum = 0;  } -bool PUSB_Setup(USBSetup& setup, u8 j) +bool PluggableUSB_::setup(USBSetup& setup)  { -	bool ret = false; -	PUSBListNode* node = rootNode; -	for (u8 i=0; i<modules_count && ret == false; i++) { -		ret = node->cb->setup(setup, j); -		node = node->next; +	PluggableUSBModule* node; +	for (node = rootNode; node; node = node->next) { +		if (node->setup(setup)) { +			return true; +		}  	} -	return ret; +	return false;  } -int8_t PUSB_AddFunction(PUSBListNode *node, u8* interface) +bool PluggableUSB_::plug(PluggableUSBModule *node)  { -	if (modules_count >= MAX_MODULES) { -		return 0; +	if ((lastEp + node->numEndpoints) > USB_ENDPOINTS) { +		return false;  	} -	if (modules_count == 0) { +	if (!rootNode) {  		rootNode = node;  	} else { -		PUSBListNode *current = rootNode; -		while(current->next != NULL) { +		PluggableUSBModule *current = rootNode; +		while (current->next) {  			current = current->next;  		}  		current->next = node;  	} -	*interface = lastIf; -	lastIf += node->cb->numInterfaces; -	for ( u8 i = 0; i< node->cb->numEndpoints; i++) { -		_initEndpoints[lastEp] = node->cb->endpointType[i]; +	node->pluggedInterface = lastIf; +	node->pluggedEndpoint = lastEp; +	lastIf += node->numInterfaces; +	for (uint8_t i = 0; i < node->numEndpoints; i++) { +		_initEndpoints[lastEp] = node->endpointType[i];  		lastEp++;  	} -	modules_count++; -	return lastEp - node->cb->numEndpoints; +	return true;  	// restart USB layer???  } +PluggableUSB_& PluggableUSB() +{ +	static PluggableUSB_ obj; +	return obj; +} + +PluggableUSB_::PluggableUSB_() : lastIf(CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT), +                                 lastEp(CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT), +                                 rootNode(NULL) +{ +	// Empty +} +  #endif -#endif /* if defined(USBCON) */
\ No newline at end of file +#endif /* if defined(USBCON) */ diff --git a/cores/arduino/PluggableUSB.h b/cores/arduino/PluggableUSB.h index d89040e..507f0df 100644 --- a/cores/arduino/PluggableUSB.h +++ b/cores/arduino/PluggableUSB.h @@ -25,38 +25,49 @@  #if defined(USBCON) -typedef struct __attribute__((packed)) -{ -  bool (*setup)(USBSetup& setup, u8 i); -  int (*getInterface)(u8* interfaceNum); -  int (*getDescriptor)(int8_t t); -  int8_t numEndpoints; -  int8_t numInterfaces; -  uint8_t *endpointType; -} PUSBCallbacks; - -typedef struct -{ -  u8 interface; -  u8 firstEndpoint; -} PUSBReturn; - -class PUSBListNode { +class PluggableUSBModule {  public: -  PUSBListNode *next = NULL; -  PUSBCallbacks *cb; -  PUSBListNode(PUSBCallbacks *ncb) {cb = ncb;} -}; +  PluggableUSBModule(uint8_t numEps, uint8_t numIfs, uint8_t *epType) : +    numEndpoints(numEps), numInterfaces(numIfs), endpointType(epType) +  { } + +protected: +  virtual bool setup(USBSetup& setup) = 0; +  virtual int getInterface(uint8_t* interfaceCount) = 0; +  virtual int getDescriptor(USBSetup& setup) = 0; +  virtual uint8_t getShortName(char *name) { name[0] = 'A'+pluggedInterface; return 1; } + +  uint8_t pluggedInterface; +  uint8_t pluggedEndpoint; -int8_t PUSB_AddFunction(PUSBListNode *node, u8 *interface); +  const uint8_t numEndpoints; +  const uint8_t numInterfaces; +  const uint8_t *endpointType; -int PUSB_GetInterface(u8* interfaceNum); +  PluggableUSBModule *next = NULL; -int PUSB_GetDescriptor(int8_t t); +  friend class PluggableUSB_; +}; -bool PUSB_Setup(USBSetup& setup, u8 i); +class PluggableUSB_ { +public: +  PluggableUSB_(); +  bool plug(PluggableUSBModule *node); +  int getInterface(uint8_t* interfaceCount); +  int getDescriptor(USBSetup& setup); +  bool setup(USBSetup& setup); +  void getShortName(char *iSerialNum); + +private: +  uint8_t lastIf; +  uint8_t lastEp; +  PluggableUSBModule* rootNode; +}; -void PUSB_Begin(); +// Replacement for global singleton. +// This function prevents static-initialization-order-fiasco +// https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use +PluggableUSB_& PluggableUSB();  #endif diff --git a/cores/arduino/Print.cpp b/cores/arduino/Print.cpp index 782d50b..bc97c85 100644 --- a/cores/arduino/Print.cpp +++ b/cores/arduino/Print.cpp @@ -17,6 +17,7 @@   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA   Modified 23 November 2006 by David A. Mellis + Modified 03 August 2015 by Chuck Todd   */  #include <stdlib.h> @@ -34,7 +35,8 @@ size_t Print::write(const uint8_t *buffer, size_t size)  {    size_t n = 0;    while (size--) { -    n += write(*buffer++); +    if (write(*buffer++)) n++; +    else break;    }    return n;  } @@ -46,7 +48,8 @@ size_t Print::print(const __FlashStringHelper *ifsh)    while (1) {      unsigned char c = pgm_read_byte(p++);      if (c == 0) break; -    n += write(c); +    if (write(c)) n++; +    else break;    }    return n;  } diff --git a/cores/arduino/Stream.cpp b/cores/arduino/Stream.cpp index b31942f..f665465 100644 --- a/cores/arduino/Stream.cpp +++ b/cores/arduino/Stream.cpp @@ -26,7 +26,6 @@  #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() @@ -54,14 +53,30 @@ int Stream::timedPeek()  // returns peek of the next digit in the stream or -1 if timeout  // discards non-numeric characters -int Stream::peekNextDigit() +int Stream::peekNextDigit(LookaheadMode lookahead, bool detectDecimal)  {    int c;    while (1) {      c = timedPeek(); -    if (c < 0) return c;  // timeout -    if (c == '-') return c; -    if (c >= '0' && c <= '9') return c; + +    if( c < 0 || +        c == '-' || +        (c >= '0' && c <= '9') || +        (detectDecimal && c == '.')) return c; + +    switch( lookahead ){ +        case SKIP_NONE: return -1; // Fail code. +        case SKIP_WHITESPACE: +            switch( c ){ +                case ' ': +                case '\t': +                case '\r': +                case '\n': break; +                default: return -1; // Fail code. +            } +        case SKIP_ALL: +            break; +    }      read();  // discard non-numeric    }  } @@ -107,31 +122,25 @@ bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t    }  } -  // 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) +// lookahead determines how parseInt looks ahead in the stream. +// See LookaheadMode enumeration at the top of the file. +// Lookahead is terminated by the first character that is not a valid part of an integer. +// Once parsing commences, 'ignore' will be skipped in the stream. +long Stream::parseInt(LookaheadMode lookahead, char ignore)  {    bool isNegative = false;    long value = 0;    int c; -  c = peekNextDigit(); +  c = peekNextDigit(lookahead, false);    // ignore non numeric leading characters    if(c < 0)      return 0; // zero returned if timeout    do{ -    if(c == skipChar) -      ; // ignore this charactor +    if(c == ignore) +      ; // ignore this character      else if(c == '-')        isNegative = true;      else if(c >= '0' && c <= '9')        // is c a digit? @@ -139,36 +148,29 @@ long Stream::parseInt(char skipChar)      read();  // consume the character we got with peek      c = timedPeek();    } -  while( (c >= '0' && c <= '9') || c == skipChar ); +  while( (c >= '0' && c <= '9') || c == ignore );    if(isNegative)      value = -value;    return value;  } -  // as parseInt but returns a floating point value -float Stream::parseFloat() +float Stream::parseFloat(LookaheadMode lookahead, char ignore)  { -  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; +  int c;    float fraction = 1.0; -  c = peekNextDigit(); +  c = peekNextDigit(lookahead, true);      // ignore non numeric leading characters    if(c < 0)      return 0; // zero returned if timeout    do{ -    if(c == skipChar) +    if(c == ignore)        ; // ignore      else if(c == '-')        isNegative = true; @@ -182,7 +184,7 @@ float Stream::parseFloat(char skipChar){      read();  // consume the character we got with peek      c = timedPeek();    } -  while( (c >= '0' && c <= '9')  || c == '.' || c == skipChar ); +  while( (c >= '0' && c <= '9')  || (c == '.' && !isFraction) || c == ignore );    if(isNegative)      value = -value; diff --git a/cores/arduino/Stream.h b/cores/arduino/Stream.h index 15f6761..db71bb6 100644 --- a/cores/arduino/Stream.h +++ b/cores/arduino/Stream.h @@ -28,13 +28,24 @@  // compatability macros for testing  /*  #define   getInt()            parseInt() -#define   getInt(skipChar)    parseInt(skipchar) +#define   getInt(ignore)    parseInt(ignore)  #define   getFloat()          parseFloat() -#define   getFloat(skipChar)  parseFloat(skipChar) +#define   getFloat(ignore)  parseFloat(ignore)  #define   getString( pre_string, post_string, buffer, length)  readBytesBetween( pre_string, terminator, buffer, length)  */ +// This enumeration provides the lookahead options for parseInt(), parseFloat() +// The rules set out here are used until either the first valid character is found +// or a time out occurs due to lack of input. +enum LookaheadMode{ +    SKIP_ALL,       // All invalid characters are ignored. +    SKIP_NONE,      // Nothing is skipped, and the stream is not touched unless the first waiting character is valid. +    SKIP_WHITESPACE // Only tabs, spaces, line feeds & carriage returns are skipped. +}; + +#define NO_IGNORE_CHAR  '\x01' // a char not found in a valid ASCII numeric field +  class Stream : public Print  {    protected: @@ -42,7 +53,7 @@ class Stream : public Print      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 +    int peekNextDigit(LookaheadMode lookahead, bool detectDecimal); // returns the next numeric digit in the stream or -1 if timeout    public:      virtual int available() = 0; @@ -72,12 +83,15 @@ class Stream : public Print    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(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR); +  // returns the first valid (long) integer value from the current position. +  // lookahead determines how parseInt looks ahead in the stream. +  // See LookaheadMode enumeration at the top of the file. +  // Lookahead is terminated by the first character that is not a valid part of an integer. +  // Once parsing commences, 'ignore' will be skipped in the stream. -  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 +  float parseFloat(LookaheadMode lookahead = SKIP_ALL, char ignore = NO_IGNORE_CHAR); +  // 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); } @@ -94,11 +108,11 @@ class Stream : public Print    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 +  long parseInt(char ignore) { return parseInt(SKIP_ALL, ignore); } +  float parseFloat(char ignore) { return parseFloat(SKIP_ALL, ignore); } +  // These overload exists for compatibility with any class that has derived +  // Stream and used parseFloat/Int with a custom ignore character. To keep +  // the public API simple, these overload remains protected.    struct MultiTarget {      const char *str;  // string you're searching for @@ -111,5 +125,5 @@ class Stream : public Print    int findMulti(struct MultiTarget *targets, int tCount);  }; - +#undef NO_IGNORE_CHAR  #endif diff --git a/cores/arduino/Tone.cpp b/cores/arduino/Tone.cpp index 7216219..1bfb3e3 100644 --- a/cores/arduino/Tone.cpp +++ b/cores/arduino/Tone.cpp @@ -209,7 +209,7 @@ static int8_t toneBegin(uint8_t _pin)          #if defined(WGM42)            bitWrite(TCCR4B, WGM42, 1);          #elif defined(CS43) -          #warning this may not be correct +          // TODO this may not be correct            // atmega32u4            bitWrite(TCCR4B, CS43, 1);          #endif @@ -485,6 +485,7 @@ void noTone(uint8_t _pin)      if (tone_pins[i] == _pin) {        _timer = pgm_read_byte(tone_pin_to_timer_PGM + i);        tone_pins[i] = 255; +      break;      }    } diff --git a/cores/arduino/USBAPI.h b/cores/arduino/USBAPI.h index 4abd961..f22ab6a 100644 --- a/cores/arduino/USBAPI.h +++ b/cores/arduino/USBAPI.h @@ -32,6 +32,12 @@ typedef unsigned long u32;  #include "Arduino.h" +// This definitions is usefull if you want to reduce the EP_SIZE to 16 +// at the moment only 64 and 16 as EP_SIZE for all EPs are supported except the control endpoint +#ifndef USB_EP_SIZE +#define USB_EP_SIZE 64 +#endif +  #if defined(USBCON)  #include "USBDesc.h" @@ -41,13 +47,13 @@ typedef unsigned long u32;  //================================================================================  //	USB -#define EP_TYPE_CONTROL				0x00 -#define EP_TYPE_BULK_IN				0x81 -#define EP_TYPE_BULK_OUT			0x80 -#define EP_TYPE_INTERRUPT_IN		0xC1 -#define EP_TYPE_INTERRUPT_OUT		0xC0 -#define EP_TYPE_ISOCHRONOUS_IN		0x41 -#define EP_TYPE_ISOCHRONOUS_OUT		0x40 +#define EP_TYPE_CONTROL				(0x00) +#define EP_TYPE_BULK_IN				((1<<EPTYPE1) | (1<<EPDIR)) +#define EP_TYPE_BULK_OUT			(1<<EPTYPE1) +#define EP_TYPE_INTERRUPT_IN		((1<<EPTYPE1) | (1<<EPTYPE0) | (1<<EPDIR)) +#define EP_TYPE_INTERRUPT_OUT		((1<<EPTYPE1) | (1<<EPTYPE0)) +#define EP_TYPE_ISOCHRONOUS_IN		((1<<EPTYPE0) | (1<<EPDIR)) +#define EP_TYPE_ISOCHRONOUS_OUT		(1<<EPTYPE0)  class USBDevice_  { @@ -69,7 +75,7 @@ extern USBDevice_ USBDevice;  struct ring_buffer;  #ifndef SERIAL_BUFFER_SIZE -#if (RAMEND < 1000) +#if ((RAMEND - RAMSTART) < 1023)  #define SERIAL_BUFFER_SIZE 16  #else  #define SERIAL_BUFFER_SIZE 64 @@ -92,6 +98,7 @@ public:  	virtual int available(void);  	virtual int peek(void);  	virtual int read(void); +	int availableForWrite(void);  	virtual void flush(void);  	virtual size_t write(uint8_t);  	virtual size_t write(const uint8_t*, size_t); @@ -101,6 +108,46 @@ public:  	volatile uint8_t _rx_buffer_head;  	volatile uint8_t _rx_buffer_tail;  	unsigned char _rx_buffer[SERIAL_BUFFER_SIZE]; + +	// This method allows processing "SEND_BREAK" requests sent by +	// the USB host. Those requests indicate that the host wants to +	// send a BREAK signal and are accompanied by a single uint16_t +	// value, specifying the duration of the break. The value 0 +	// means to end any current break, while the value 0xffff means +	// to start an indefinite break. +	// readBreak() will return the value of the most recent break +	// request, but will return it at most once, returning -1 when +	// readBreak() is called again (until another break request is +	// received, which is again returned once). +	// This also mean that if two break requests are received +	// without readBreak() being called in between, the value of the +	// first request is lost. +	// Note that the value returned is a long, so it can return +	// 0-0xffff as well as -1. +	int32_t readBreak(); + +	// These return the settings specified by the USB host for the +	// serial port. These aren't really used, but are offered here +	// in case a sketch wants to act on these settings. +	uint32_t baud(); +	uint8_t stopbits(); +	uint8_t paritytype(); +	uint8_t numbits(); +	bool dtr(); +	bool rts(); +	enum { +		ONE_STOP_BIT = 0, +		ONE_AND_HALF_STOP_BIT = 1, +		TWO_STOP_BITS = 2, +	}; +	enum { +		NO_PARITY = 0, +		ODD_PARITY = 1, +		EVEN_PARITY = 2, +		MARK_PARITY = 3, +		SPACE_PARITY = 4, +	}; +  };  extern Serial_ Serial; @@ -148,6 +195,7 @@ int USB_SendControl(uint8_t flags, const void* d, int len);  int USB_RecvControl(void* d, int len);  uint8_t	USB_Available(uint8_t ep); +uint8_t USB_SendSpace(uint8_t ep);  int USB_Send(uint8_t ep, const void* data, int len);	// blocking  int USB_Recv(uint8_t ep, void* data, int len);		// non-blocking  int USB_Recv(uint8_t ep);							// non-blocking diff --git a/cores/arduino/USBCore.cpp b/cores/arduino/USBCore.cpp index 8237ccb..3c6610c 100644 --- a/cores/arduino/USBCore.cpp +++ b/cores/arduino/USBCore.cpp @@ -18,6 +18,7 @@  #include "USBAPI.h"  #include "PluggableUSB.h" +#include <stdlib.h>  #if defined(USBCON) @@ -69,10 +70,10 @@ const u8 STRING_MANUFACTURER[] PROGMEM = USB_MANUFACTURER;  //	DEVICE DESCRIPTOR  const DeviceDescriptor USB_DeviceDescriptor = -	D_DEVICE(0x00,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1); +	D_DEVICE(0x00,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,ISERIAL,1);  const DeviceDescriptor USB_DeviceDescriptorB = -	D_DEVICE(0xEF,0x02,0x01,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1); +	D_DEVICE(0xEF,0x02,0x01,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,ISERIAL,1);  //==================================================================  //================================================================== @@ -110,7 +111,7 @@ static inline void ClearOUT(void)  	UEINTX = ~(1<<RXOUTI);  } -void Recv(volatile u8* data, u8 count) +static inline void Recv(volatile u8* data, u8 count)  {  	while (count--)  		*data++ = UEDATX; @@ -253,7 +254,7 @@ u8 USB_SendSpace(u8 ep)  	LockEP lock(ep);  	if (!ReadWriteAllowed())  		return 0; -	return 64 - FifoByteCount(); +	return USB_EP_SIZE - FifoByteCount();  }  //	Blocking Send of data to an endpoint @@ -308,24 +309,20 @@ int USB_Send(u8 ep, const void* d, int len)  	return r;  } -u8 _initEndpoints[] = +u8 _initEndpoints[USB_ENDPOINTS] =  { -	0, +	0,                      // Control Endpoint -	EP_TYPE_INTERRUPT_IN,		// CDC_ENDPOINT_ACM -	EP_TYPE_BULK_OUT,			// CDC_ENDPOINT_OUT -	EP_TYPE_BULK_IN,			// CDC_ENDPOINT_IN +	EP_TYPE_INTERRUPT_IN,   // CDC_ENDPOINT_ACM +	EP_TYPE_BULK_OUT,       // CDC_ENDPOINT_OUT +	EP_TYPE_BULK_IN,        // CDC_ENDPOINT_IN -#ifdef PLUGGABLE_USB_ENABLED -	//allocate 3 endpoints and remove const so they can be changed by the user -	0, -	0, -	0, -#endif +	// Following endpoints are automatically initialized to 0  };  #define EP_SINGLE_64 0x32	// EP0  #define EP_DOUBLE_64 0x36	// Other endpoints +#define EP_SINGLE_16 0x12  static  void InitEP(u8 index, u8 type, u8 size) @@ -344,7 +341,13 @@ void InitEndpoints()  		UENUM = i;  		UECONX = (1<<EPEN);  		UECFG0X = _initEndpoints[i]; +#if USB_EP_SIZE == 16 +		UECFG1X = EP_SINGLE_16; +#elif USB_EP_SIZE == 64  		UECFG1X = EP_DOUBLE_64; +#else +#error Unsupported value for USB_EP_SIZE +#endif  	}  	UERST = 0x7E;	// And reset them  	UERST = 0; @@ -360,13 +363,13 @@ bool ClassInterfaceRequest(USBSetup& setup)  		return CDC_Setup(setup);  #ifdef PLUGGABLE_USB_ENABLED -	return PUSB_Setup(setup, i); +	return PluggableUSB().setup(setup);  #endif  	return false;  } -int _cmark; -int _cend; +static int _cmark; +static int _cend;  void InitControl(int end)  {  	SetEP(0); @@ -407,11 +410,12 @@ int USB_SendControl(u8 flags, const void* d, int len)  // Send a USB descriptor string. The string is stored in PROGMEM as a  // plain ASCII string but is sent out as UTF-16 with the correct 2-byte  // prefix -static bool USB_SendStringDescriptor(const u8*string_P, u8 string_len) { +static bool USB_SendStringDescriptor(const u8*string_P, u8 string_len, uint8_t flags) {          SendControl(2 + string_len * 2);          SendControl(3); +        bool pgm = flags & TRANSFER_PGM;          for(u8 i = 0; i < string_len; i++) { -                bool r = SendControl(pgm_read_byte(&string_P[i])); +                bool r = SendControl(pgm ? pgm_read_byte(&string_P[i]) : string_P[i]);                  r &= SendControl(0); // high byte                  if(!r) {                          return false; @@ -431,14 +435,14 @@ int USB_RecvControl(void* d, int len)  	return len;  } -int SendInterfaces() +static u8 SendInterfaces()  {  	u8 interfaces = 0;  	CDC_GetInterface(&interfaces);  #ifdef PLUGGABLE_USB_ENABLED -	PUSB_GetInterface(&interfaces); +	PluggableUSB().getInterface(&interfaces);  #endif  	return interfaces; @@ -452,7 +456,7 @@ bool SendConfiguration(int maxlen)  {  	//	Count and measure interfaces  	InitControl(0);	 -	int interfaces = SendInterfaces(); +	u8 interfaces = SendInterfaces();  	ConfigDescriptor config = D_CONFIG(_cmark + sizeof(ConfigDescriptor),interfaces);  	//	Now send them @@ -462,7 +466,7 @@ bool SendConfiguration(int maxlen)  	return true;  } -u8 _cdcComposite = 0; +static u8 _cdcComposite = 0;  static  bool SendDescriptor(USBSetup& setup) @@ -474,7 +478,7 @@ bool SendDescriptor(USBSetup& setup)  	InitControl(setup.wLength);  #ifdef PLUGGABLE_USB_ENABLED -	ret = PUSB_GetDescriptor(t); +	ret = PluggableUSB().getDescriptor(setup);  	if (ret != 0) {  		return (ret > 0 ? true : false);  	} @@ -493,10 +497,17 @@ bool SendDescriptor(USBSetup& setup)  			desc_addr = (const u8*)&STRING_LANGUAGE;  		}  		else if (setup.wValueL == IPRODUCT) { -			return USB_SendStringDescriptor(STRING_PRODUCT, strlen(USB_PRODUCT)); +			return USB_SendStringDescriptor(STRING_PRODUCT, strlen(USB_PRODUCT), TRANSFER_PGM);  		}  		else if (setup.wValueL == IMANUFACTURER) { -			return USB_SendStringDescriptor(STRING_MANUFACTURER, strlen(USB_MANUFACTURER)); +			return USB_SendStringDescriptor(STRING_MANUFACTURER, strlen(USB_MANUFACTURER), TRANSFER_PGM); +		} +		else if (setup.wValueL == ISERIAL) { +#ifdef PLUGGABLE_USB_ENABLED +			char name[ISERIAL_MAX_LEN]; +			PluggableUSB().getShortName(name); +			return USB_SendStringDescriptor((uint8_t*)name, strlen(name), 0); +#endif  		}  		else  			return false; @@ -620,13 +631,19 @@ void USB_Flush(u8 ep)  static inline void USB_ClockDisable()  { +#if defined(OTGPADE)  	USBCON = (USBCON & ~(1<<OTGPADE)) | (1<<FRZCLK); // freeze clock and disable VBUS Pad +#else // u2 Series +	USBCON = (1 << FRZCLK); // freeze clock +#endif  	PLLCSR &= ~(1<<PLLE);  // stop PLL  }  static inline void USB_ClockEnable()  { +#if defined(UHWCON)  	UHWCON |= (1<<UVREGE);			// power internal reg +#endif  	USBCON = (1<<USBE) | (1<<FRZCLK);	// clock frozen, usb enabled  // ATmega32U4 @@ -639,6 +656,16 @@ static inline void USB_ClockEnable()  #error "Clock rate of F_CPU not supported"  #endif +#elif defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__) +	// for the u2 Series the datasheet is confusing. On page 40 its called PINDIV and on page 290 its called PLLP0 +#if F_CPU == 16000000UL +	// Need 16 MHz xtal +	PLLCSR |= (1 << PLLP0); +#elif F_CPU == 8000000UL +	// Need 8 MHz xtal +	PLLCSR &= ~(1 << PLLP0); +#endif +  // AT90USB646, AT90USB647, AT90USB1286, AT90USB1287  #elif defined(PLLP2)  #if F_CPU == 16000000UL @@ -670,10 +697,18 @@ static inline void USB_ClockEnable()  	// strange behaviors when the board is reset using the serial  	// port touch at 1200 bps. This delay fixes this behavior.  	delay(1); +#if defined(OTGPADE)  	USBCON = (USBCON & ~(1<<FRZCLK)) | (1<<OTGPADE);	// start USB clock, enable VBUS Pad +#else +	USBCON &= ~(1 << FRZCLK);	// start USB clock +#endif  #if defined(RSTCPU) +#if defined(LSM)  	UDCON &= ~((1<<RSTCPU) | (1<<LSM) | (1<<RMWKUP) | (1<<DETACH));	// enable attach resistor, set full speed mode +#else // u2 Series +	UDCON &= ~((1 << RSTCPU) | (1 << RMWKUP) | (1 << DETACH));	// enable attach resistor, set full speed mode +#endif  #else  	// AT90USB64x and AT90USB128x don't have RSTCPU  	UDCON &= ~((1<<LSM) | (1<<RMWKUP) | (1<<DETACH));	// enable attach resistor, set full speed mode diff --git a/cores/arduino/USBCore.h b/cores/arduino/USBCore.h index 66f8c05..4e08d71 100644 --- a/cores/arduino/USBCore.h +++ b/cores/arduino/USBCore.h @@ -49,14 +49,16 @@  #define REQUEST_OTHER			0x03  #define REQUEST_RECIPIENT		0x03 -#define REQUEST_DEVICETOHOST_CLASS_INTERFACE  (REQUEST_DEVICETOHOST + REQUEST_CLASS + REQUEST_INTERFACE) -#define REQUEST_HOSTTODEVICE_CLASS_INTERFACE  (REQUEST_HOSTTODEVICE + REQUEST_CLASS + REQUEST_INTERFACE) +#define REQUEST_DEVICETOHOST_CLASS_INTERFACE    (REQUEST_DEVICETOHOST | REQUEST_CLASS | REQUEST_INTERFACE) +#define REQUEST_HOSTTODEVICE_CLASS_INTERFACE    (REQUEST_HOSTTODEVICE | REQUEST_CLASS | REQUEST_INTERFACE) +#define REQUEST_DEVICETOHOST_STANDARD_INTERFACE (REQUEST_DEVICETOHOST | REQUEST_STANDARD | REQUEST_INTERFACE)  //	Class requests  #define CDC_SET_LINE_CODING			0x20  #define CDC_GET_LINE_CODING			0x21  #define CDC_SET_CONTROL_LINE_STATE	0x22 +#define CDC_SEND_BREAK				0x23  #define MSC_RESET					0xFF  #define MSC_GET_MAX_LUN				0xFE @@ -98,8 +100,8 @@  // bEndpointAddress in Endpoint Descriptor  #define USB_ENDPOINT_DIRECTION_MASK            0x80 -#define USB_ENDPOINT_OUT(addr)                 ((addr) | 0x00) -#define USB_ENDPOINT_IN(addr)                  ((addr) | 0x80) +#define USB_ENDPOINT_OUT(addr)                 (lowByte((addr) | 0x00)) +#define USB_ENDPOINT_IN(addr)                  (lowByte((addr) | 0x80))  #define USB_ENDPOINT_TYPE_MASK                 0x03  #define USB_ENDPOINT_TYPE_CONTROL              0x00 @@ -276,4 +278,4 @@ typedef struct  #define D_CDCCS4(_subtype,_d0)		{ 4, 0x24, _subtype, _d0 } -#endif
\ No newline at end of file +#endif diff --git a/cores/arduino/USBDesc.h b/cores/arduino/USBDesc.h index 1962727..c0dce07 100644 --- a/cores/arduino/USBDesc.h +++ b/cores/arduino/USBDesc.h @@ -1,23 +1,30 @@ - - -/* Copyright (c) 2011, Peter Barrett   -**   -** Permission to use, copy, modify, and/or distribute this software for   -** any purpose with or without fee is hereby granted, provided that the   -** above copyright notice and this permission notice appear in all copies.   -**  -** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL   -** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED   -** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR   -** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES   -** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,   -** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,   -** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS   -** SOFTWARE.   -*/ +/* +   Copyright (c) 2011, Peter Barrett +   Copyright (c) 2015, Arduino LLC + +   Permission to use, copy, modify, and/or distribute this software for +   any purpose with or without fee is hereby granted, provided that the +   above copyright notice and this permission notice appear in all copies. + +   THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +   WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +   WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR +   BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES +   OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +   WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +   ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +   SOFTWARE. + */  #define PLUGGABLE_USB_ENABLED +#if defined(EPRST6) +#define USB_ENDPOINTS 7 // AtMegaxxU4 +#else +#define USB_ENDPOINTS 5 // AtMegaxxU2 +#endif + +#define ISERIAL_MAX_LEN     20  #define CDC_INTERFACE_COUNT	2  #define CDC_ENPOINT_COUNT	3 @@ -34,6 +41,6 @@  #define CDC_RX CDC_ENDPOINT_OUT  #define CDC_TX CDC_ENDPOINT_IN -#define IMANUFACTURER	1 -#define IPRODUCT		2 - +#define IMANUFACTURER   1 +#define IPRODUCT        2 +#define ISERIAL         3
\ No newline at end of file diff --git a/cores/arduino/WInterrupts.c b/cores/arduino/WInterrupts.c index 71dd45c..7e9f717 100644 --- a/cores/arduino/WInterrupts.c +++ b/cores/arduino/WInterrupts.c @@ -32,7 +32,39 @@  #include "wiring_private.h" -static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS]; +static void nothing(void) { +} + +static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS] = { +#if EXTERNAL_NUM_INTERRUPTS > 8 +    #warning There are more than 8 external interrupts. Some callbacks may not be initialized. +    nothing, +#endif +#if EXTERNAL_NUM_INTERRUPTS > 7 +    nothing, +#endif +#if EXTERNAL_NUM_INTERRUPTS > 6 +    nothing, +#endif +#if EXTERNAL_NUM_INTERRUPTS > 5 +    nothing, +#endif +#if EXTERNAL_NUM_INTERRUPTS > 4 +    nothing, +#endif +#if EXTERNAL_NUM_INTERRUPTS > 3 +    nothing, +#endif +#if EXTERNAL_NUM_INTERRUPTS > 2 +    nothing, +#endif +#if EXTERNAL_NUM_INTERRUPTS > 1 +    nothing, +#endif +#if EXTERNAL_NUM_INTERRUPTS > 0 +    nothing, +#endif +};  // volatile static voidFuncPtr twiIntFunc;  void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) { @@ -238,7 +270,7 @@ void detachInterrupt(uint8_t interruptNum) {  #endif      } -    intFunc[interruptNum] = 0; +    intFunc[interruptNum] = nothing;    }  } @@ -250,87 +282,71 @@ void attachInterruptTwi(void (*userFunc)(void) ) {  #if defined(__AVR_ATmega32U4__)  ISR(INT0_vect) { -	if(intFunc[EXTERNAL_INT_0]) -		intFunc[EXTERNAL_INT_0](); +    intFunc[EXTERNAL_INT_0]();  }  ISR(INT1_vect) { -	if(intFunc[EXTERNAL_INT_1]) -		intFunc[EXTERNAL_INT_1](); +    intFunc[EXTERNAL_INT_1]();  }  ISR(INT2_vect) { -    if(intFunc[EXTERNAL_INT_2]) -		intFunc[EXTERNAL_INT_2](); +    intFunc[EXTERNAL_INT_2]();  }  ISR(INT3_vect) { -    if(intFunc[EXTERNAL_INT_3]) -		intFunc[EXTERNAL_INT_3](); +    intFunc[EXTERNAL_INT_3]();  }  ISR(INT6_vect) { -    if(intFunc[EXTERNAL_INT_4]) -		intFunc[EXTERNAL_INT_4](); +    intFunc[EXTERNAL_INT_4]();  }  #elif defined(EICRA) && defined(EICRB)  ISR(INT0_vect) { -  if(intFunc[EXTERNAL_INT_2])      intFunc[EXTERNAL_INT_2]();  }  ISR(INT1_vect) { -  if(intFunc[EXTERNAL_INT_3])      intFunc[EXTERNAL_INT_3]();  }  ISR(INT2_vect) { -  if(intFunc[EXTERNAL_INT_4])      intFunc[EXTERNAL_INT_4]();  }  ISR(INT3_vect) { -  if(intFunc[EXTERNAL_INT_5])      intFunc[EXTERNAL_INT_5]();  }  ISR(INT4_vect) { -  if(intFunc[EXTERNAL_INT_0])      intFunc[EXTERNAL_INT_0]();  }  ISR(INT5_vect) { -  if(intFunc[EXTERNAL_INT_1])      intFunc[EXTERNAL_INT_1]();  }  ISR(INT6_vect) { -  if(intFunc[EXTERNAL_INT_6])      intFunc[EXTERNAL_INT_6]();  }  ISR(INT7_vect) { -  if(intFunc[EXTERNAL_INT_7])      intFunc[EXTERNAL_INT_7]();  }  #else  ISR(INT0_vect) { -  if(intFunc[EXTERNAL_INT_0])      intFunc[EXTERNAL_INT_0]();  }  ISR(INT1_vect) { -  if(intFunc[EXTERNAL_INT_1])      intFunc[EXTERNAL_INT_1]();  }  #if defined(EICRA) && defined(ISC20)  ISR(INT2_vect) { -  if(intFunc[EXTERNAL_INT_2])      intFunc[EXTERNAL_INT_2]();  }  #endif diff --git a/cores/arduino/wiring.c b/cores/arduino/wiring.c index f1a14ef..1c3e5a5 100644 --- a/cores/arduino/wiring.c +++ b/cores/arduino/wiring.c @@ -303,8 +303,6 @@ void init()  	// put timer 1 in 8-bit phase correct pwm mode  #if defined(TCCR1A) && defined(WGM10)  	sbi(TCCR1A, WGM10); -#elif defined(TCCR1) -	#warning this needs to be finished  #endif  	// set timer 2 prescale factor to 64 @@ -312,8 +310,8 @@ void init()  	sbi(TCCR2, CS22);  #elif defined(TCCR2B) && defined(CS22)  	sbi(TCCR2B, CS22); -#else -	#warning Timer 2 not finished (may not be present on this CPU) +//#else +	// Timer 2 not finished (may not be present on this CPU)  #endif  	// configure timer 2 for phase correct pwm (8-bit) @@ -321,8 +319,8 @@ void init()  	sbi(TCCR2, WGM20);  #elif defined(TCCR2A) && defined(WGM20)  	sbi(TCCR2A, WGM20); -#else -	#warning Timer 2 not finished (may not be present on this CPU) +//#else +	// Timer 2 not finished (may not be present on this CPU)  #endif  #if defined(TCCR3B) && defined(CS31) && defined(WGM30) diff --git a/cores/arduino/wiring_digital.c b/cores/arduino/wiring_digital.c index 51adb2c..27a62fc 100644 --- a/cores/arduino/wiring_digital.c +++ b/cores/arduino/wiring_digital.c @@ -94,7 +94,7 @@ static void turnOffPWM(uint8_t timer)  		case  TIMER0A:  cbi(TCCR0A, COM0A1);    break;  		#endif -		#if defined(TIMER0B) && defined(COM0B1) +		#if defined(TCCR0A) && defined(COM0B1)  		case  TIMER0B:  cbi(TCCR0A, COM0B1);    break;  		#endif  		#if defined(TCCR2A) && defined(COM2A1) diff --git a/cores/arduino/wiring_private.h b/cores/arduino/wiring_private.h index ed7c8f0..a277b14 100644 --- a/cores/arduino/wiring_private.h +++ b/cores/arduino/wiring_private.h @@ -52,7 +52,8 @@ uint32_t countPulseASM(volatile uint8_t *port, uint8_t bit, uint8_t stateMask, u  #define EXTERNAL_INT_6 6  #define EXTERNAL_INT_7 7 -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega256RFR2__) +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega256RFR2__) || \ +    defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__)  #define EXTERNAL_NUM_INTERRUPTS 8  #elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__)  #define EXTERNAL_NUM_INTERRUPTS 3 diff --git a/cores/arduino/wiring_pulse.c b/cores/arduino/wiring_pulse.c index 76383e9..d6e0434 100644 --- a/cores/arduino/wiring_pulse.c +++ b/cores/arduino/wiring_pulse.c @@ -69,25 +69,24 @@ unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout)  	uint8_t port = digitalPinToPort(pin);  	uint8_t stateMask = (state ? bit : 0); -	// convert the timeout from microseconds to a number of times through -	// the initial loop; it takes 16 clock cycles per iteration. -	unsigned long numloops = 0; -	unsigned long maxloops = microsecondsToClockCycles(timeout); +	unsigned long startMicros = micros();  	// wait for any previous pulse to end -	while ((*portInputRegister(port) & bit) == stateMask) -		if (numloops++ == maxloops) +	while ((*portInputRegister(port) & bit) == stateMask) { +		if (micros() - startMicros > timeout)  			return 0; +	}  	// wait for the pulse to start -	while ((*portInputRegister(port) & bit) != stateMask) -		if (numloops++ == maxloops) +	while ((*portInputRegister(port) & bit) != stateMask) { +		if (micros() - startMicros > timeout)  			return 0; +	}  	unsigned long start = micros();  	// wait for the pulse to stop  	while ((*portInputRegister(port) & bit) == stateMask) { -		if (numloops++ == maxloops) +		if (micros() - startMicros > timeout)  			return 0;  	}  	return micros() - start;  | 
