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