diff options
Diffstat (limited to 'cores')
| -rwxr-xr-x | cores/arduino/Arduino.h | 1 | ||||
| -rw-r--r-- | cores/arduino/CDC.cpp | 106 | ||||
| -rw-r--r-- | cores/arduino/HID.cpp | 144 | ||||
| -rw-r--r-- | cores/arduino/HardwareSerial.cpp | 8 | ||||
| -rw-r--r-- | cores/arduino/HardwareSerial.h | 1 | ||||
| -rwxr-xr-x | cores/arduino/Print.cpp | 5 | ||||
| -rwxr-xr-x | cores/arduino/Print.h | 5 | ||||
| -rw-r--r-- | cores/arduino/Stream.cpp | 44 | ||||
| -rw-r--r-- | cores/arduino/Stream.h | 2 | ||||
| -rw-r--r-- | cores/arduino/USBAPI.h | 82 | ||||
| -rw-r--r-- | cores/arduino/USBCore.cpp | 34 | ||||
| -rw-r--r-- | cores/arduino/USBDesc.h | 4 | ||||
| -rw-r--r--[-rwxr-xr-x] | cores/arduino/WInterrupts.c | 66 | ||||
| -rw-r--r-- | cores/arduino/WString.cpp | 4 | ||||
| -rw-r--r--[-rwxr-xr-x] | cores/arduino/main.cpp | 2 | ||||
| -rw-r--r--[-rwxr-xr-x] | cores/arduino/wiring.c | 11 | ||||
| -rw-r--r-- | cores/arduino/wiring_analog.c | 26 | ||||
| -rw-r--r--[-rwxr-xr-x] | cores/arduino/wiring_digital.c | 18 | ||||
| -rwxr-xr-x | cores/arduino/wiring_private.h | 2 | 
19 files changed, 430 insertions, 135 deletions
| diff --git a/cores/arduino/Arduino.h b/cores/arduino/Arduino.h index bfec943..830c995 100755 --- a/cores/arduino/Arduino.h +++ b/cores/arduino/Arduino.h @@ -20,6 +20,7 @@ extern "C"{  #define INPUT 0x0  #define OUTPUT 0x1 +#define INPUT_PULLUP 0x2  #define true 0x1  #define false 0x0 diff --git a/cores/arduino/CDC.cpp b/cores/arduino/CDC.cpp index 14a0eae..1ee3a48 100644 --- a/cores/arduino/CDC.cpp +++ b/cores/arduino/CDC.cpp @@ -23,12 +23,20 @@  #if defined(USBCON)  #ifdef CDC_ENABLED -void Reboot() +#if (RAMEND < 1000) +#define SERIAL_BUFFER_SIZE 16 +#else +#define SERIAL_BUFFER_SIZE 64 +#endif + +struct ring_buffer  { -	USB.detach(); -	cli(); -	asm volatile("jmp 0x7800");		// jump to bootloader - DiskLoader takes up last 2 kB -} +	unsigned char buffer[SERIAL_BUFFER_SIZE]; +	volatile int head; +	volatile int tail; +}; + +ring_buffer cdc_rx_buffer = { { 0 }, 0, 0};  typedef struct  { @@ -92,9 +100,28 @@ bool WEAK CDC_Setup(Setup& setup)  		if (CDC_SET_CONTROL_LINE_STATE == r)  		{ -			if (0 != _usbLineInfo.lineState && 1200 == _usbLineInfo.dwDTERate)	// auto-reset is triggered when the port, already open at 1200 bps, is closed -				Reboot();  			_usbLineInfo.lineState = setup.wValueL; + +			// auto-reset into the bootloader is triggered when the port, already  +			// open at 1200 bps, is closed.  this is the signal to start the watchdog +			// with a relatively long period so it can finish housekeeping tasks +			// like servicing endpoints before the sketch ends +			if (1200 == _usbLineInfo.dwDTERate) { +				// We check DTR state to determine if host port is open (bit 0 of lineState). +				if ((_usbLineInfo.lineState & 0x01) == 0) { +					*(uint16_t *)0x0800 = 0x7777; +					wdt_enable(WDTO_120MS); +				} else { +					// Most OSs do some intermediate steps when configuring ports and DTR can +					// twiggle more than once before stabilizing. +					// To avoid spurious resets we set the watchdog to 250ms and eventually +					// cancel if DTR goes back high. +	 +					wdt_disable(); +					wdt_reset(); +					*(uint16_t *)0x0800 = 0x0; +				} +			}  			return true;  		}  	} @@ -111,33 +138,49 @@ void Serial_::end(void)  {  } +void Serial_::accept(void)  +{ +	ring_buffer *buffer = &cdc_rx_buffer; +	int c = USB_Recv(CDC_RX);  +	int i = (unsigned int)(buffer->head+1) % SERIAL_BUFFER_SIZE; +	 +	// if we should be storing the received character into the location +	// just before the tail (meaning that the head would advance to the +	// current location of the tail), we're about to overflow the buffer +	// and so we don't write the character or advance the head. +	if (i != buffer->tail) { +		buffer->buffer[buffer->head] = c; +		buffer->head = i; +	} +} +  int Serial_::available(void)  { -	u8 avail = USB_Available(CDC_RX); -	if (_serialPeek != -1) -		avail++; -	return avail; +	ring_buffer *buffer = &cdc_rx_buffer; +	return (unsigned int)(SERIAL_BUFFER_SIZE + buffer->head - buffer->tail) % SERIAL_BUFFER_SIZE;  } -//	peek is nasty  int Serial_::peek(void)  { -	if (_serialPeek == -1) -		_serialPeek = read(); -	return _serialPeek; +	ring_buffer *buffer = &cdc_rx_buffer; +	if (buffer->head == buffer->tail) { +		return -1; +	} else { +		return buffer->buffer[buffer->tail]; +	}  }  int Serial_::read(void)  { -	int c; -	if (_serialPeek != -1) -	{ -		c = _serialPeek; -		_serialPeek = -1; +	ring_buffer *buffer = &cdc_rx_buffer; +	// if the head isn't ahead of the tail, we don't have any characters +	if (buffer->head == buffer->tail) { +		return -1;  	} else { -		c = USB_Recv(CDC_RX); -	} -	return c; +		unsigned char c = buffer->buffer[buffer->tail]; +		buffer->tail = (unsigned int)(buffer->tail + 1) % SERIAL_BUFFER_SIZE; +		return c; +	}	  }  void Serial_::flush(void) @@ -169,7 +212,22 @@ size_t Serial_::write(uint8_t c)  	return 0;  } +// This operator is a convenient way for a sketch to check whether the +// port has actually been configured and opened by the host (as opposed +// to just being connected to the host).  It can be used, for example, in  +// setup() before printing to ensure that an application on the host is +// actually ready to receive and display the data. +// We add a short delay before returning to fix a bug observed by Federico +// where the port is configured (lineState != 0) but not quite opened. +Serial_::operator bool() { +	bool result = false; +	if (_usbLineInfo.lineState > 0)  +		result = true; +	delay(10); +	return result; +} +  Serial_ Serial;  #endif -#endif /* if defined(USBCON) */
\ No newline at end of file +#endif /* if defined(USBCON) */ diff --git a/cores/arduino/HID.cpp b/cores/arduino/HID.cpp index 8ed1566..ac63608 100644 --- a/cores/arduino/HID.cpp +++ b/cores/arduino/HID.cpp @@ -144,7 +144,6 @@ u8 _hid_protocol = 1;  u8 _hid_idle = 1;  #define WEAK __attribute__ ((weak)) -#define WEAK   int WEAK HID_GetInterface(u8* interfaceNum)  { @@ -202,7 +201,15 @@ bool WEAK HID_Setup(Setup& setup)  //================================================================================  //	Mouse -Mouse_::Mouse_() : _buttons(0) +Mouse_::Mouse_(void) : _buttons(0) +{ +} + +void Mouse_::begin(void)  +{ +} + +void Mouse_::end(void)   {  } @@ -245,7 +252,7 @@ void Mouse_::release(uint8_t b)  bool Mouse_::isPressed(uint8_t b)  { -	if (b & _buttons > 0)  +	if ((b & _buttons) > 0)   		return true;  	return false;  } @@ -254,18 +261,21 @@ bool Mouse_::isPressed(uint8_t b)  //================================================================================  //	Keyboard -Keyboard_::Keyboard_() : _keyMap(0) +Keyboard_::Keyboard_(void)   {  } -void Keyboard_::sendReport(KeyReport* keys) +void Keyboard_::begin(void)  +{ +} + +void Keyboard_::end(void)   { -	HID_SendReport(2,keys,sizeof(KeyReport));  } -void Keyboard_::setKeyMap(KeyMap* keyMap) +void Keyboard_::sendReport(KeyReport* keys)  { -	_keyMap = keyMap; +	HID_SendReport(2,keys,sizeof(KeyReport));  }  extern @@ -406,41 +416,105 @@ const uint8_t _asciimap[128] =  };  uint8_t USBPutChar(uint8_t c); -size_t Keyboard_::write(uint8_t c) + +// press() adds the specified key (printing, non-printing, or modifier) +// to the persistent key report and sends the report.  Because of the way  +// USB HID works, the host acts like the key remains pressed until we  +// call release(), releaseAll(), or otherwise clear the report and resend. +size_t Keyboard_::press(uint8_t k)   { -	// Keydown -	{ -		KeyReport keys = {0}; -		if (_keyMap) -			_keyMap->charToKey(c,&keys); -		else -		{ -			if (c >= 128) { -				setWriteError(); -				return 0; -			} -			c = pgm_read_byte(_asciimap + c); -			if (!c) { -				setWriteError(); -				return 0; -			} -			if (c & 0x80) -			{ -				keys.modifiers |= KEY_MODIFIER_LEFT_SHIFT; -				c &= 0x7F; +	uint8_t i; +	if (k >= 136) {			// it's a non-printing key (not a modifier) +		k = k - 136; +	} else if (k >= 128) {	// it's a modifier key +		_keyReport.modifiers |= (1<<(k-128)); +		k = 0; +	} else {				// it's a printing key +		k = pgm_read_byte(_asciimap + k); +		if (!k) { +			setWriteError(); +			return 0; +		} +		if (k & 0x80) {						// it's a capital letter or other character reached with shift +			_keyReport.modifiers |= 0x02;	// the left shift modifier +			k &= 0x7F; +		} +	} +	 +	// Add k to the key report only if it's not already present +	// and if there is an empty slot. +	if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&  +		_keyReport.keys[2] != k && _keyReport.keys[3] != k && +		_keyReport.keys[4] != k && _keyReport.keys[5] != k) { +		 +		for (i=0; i<6; i++) { +			if (_keyReport.keys[i] == 0x00) { +				_keyReport.keys[i] = k; +				break;  			} -			keys.keys[0] = c;  		} -		sendReport(&keys); +		if (i == 6) { +			setWriteError(); +			return 0; +		}	  	} -	//	Keyup -	{ -		KeyReport keys = {0}; -		sendReport(&keys); +	sendReport(&_keyReport); +	return 1; +} + +// release() takes the specified key out of the persistent key report and +// sends the report.  This tells the OS the key is no longer pressed and that +// it shouldn't be repeated any more. +size_t Keyboard_::release(uint8_t k)  +{ +	uint8_t i; +	if (k >= 136) {			// it's a non-printing key (not a modifier) +		k = k - 136; +	} else if (k >= 128) {	// it's a modifier key +		_keyReport.modifiers &= ~(1<<(k-128)); +		k = 0; +	} else {				// it's a printing key +		k = pgm_read_byte(_asciimap + k); +		if (!k) { +			return 0; +		} +		if (k & 0x80) {							// it's a capital letter or other character reached with shift +			_keyReport.modifiers &= ~(0x02);	// the left shift modifier +			k &= 0x7F; +		}  	} +	 +	// Test the key report to see if k is present.  Clear it if it exists. +	// Check all positions in case the key is present more than once (which it shouldn't be) +	for (i=0; i<6; i++) { +		if (0 != k && _keyReport.keys[i] == k) { +			_keyReport.keys[i] = 0x00; +		} +	} + +	sendReport(&_keyReport);  	return 1;  } +void Keyboard_::releaseAll(void) +{ +	_keyReport.keys[0] = 0; +	_keyReport.keys[1] = 0;	 +	_keyReport.keys[2] = 0; +	_keyReport.keys[3] = 0;	 +	_keyReport.keys[4] = 0; +	_keyReport.keys[5] = 0;	 +	_keyReport.modifiers = 0; +	sendReport(&_keyReport); +} + +size_t Keyboard_::write(uint8_t c) +{	 +	uint8_t p = press(c);		// Keydown +	uint8_t r = release(c);		// Keyup +	return (p);					// just return the result of press() since release() almost always returns 1 +} +  #endif  #endif /* if defined(USBCON) */
\ No newline at end of file diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index 1b1fa71..f40ddee 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -46,8 +46,8 @@  struct ring_buffer  {    unsigned char buffer[SERIAL_BUFFER_SIZE]; -  volatile int head; -  volatile int tail; +  volatile unsigned int head; +  volatile unsigned int tail;  };  #if defined(USBCON) @@ -398,6 +398,10 @@ size_t HardwareSerial::write(uint8_t c)    return 1;  } +HardwareSerial::operator bool() { +	return true; +} +  // Preinstantiate Objects //////////////////////////////////////////////////////  #if defined(UBRRH) && defined(UBRRL) diff --git a/cores/arduino/HardwareSerial.h b/cores/arduino/HardwareSerial.h index 176abe1..bf4924c 100644 --- a/cores/arduino/HardwareSerial.h +++ b/cores/arduino/HardwareSerial.h @@ -57,6 +57,7 @@ class HardwareSerial : public Stream      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();  };  #if defined(UBRRH) || defined(UBRR0H) diff --git a/cores/arduino/Print.cpp b/cores/arduino/Print.cpp index ff9b154..711251c 100755 --- a/cores/arduino/Print.cpp +++ b/cores/arduino/Print.cpp @@ -41,7 +41,7 @@ size_t Print::write(const uint8_t *buffer, size_t size)  size_t Print::print(const __FlashStringHelper *ifsh)  { -  const prog_char *p = (const prog_char *)ifsh; +  const char PROGMEM *p = (const char PROGMEM *)ifsh;    size_t n = 0;    while (1) {      unsigned char c = pgm_read_byte(p++); @@ -226,6 +226,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/cores/arduino/Print.h b/cores/arduino/Print.h index 1af6b72..dc76150 100755 --- a/cores/arduino/Print.h +++ b/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/cores/arduino/Stream.cpp b/cores/arduino/Stream.cpp index 5fad8dd..aafb7fc 100644 --- a/cores/arduino/Stream.cpp +++ b/cores/arduino/Stream.cpp @@ -99,25 +99,27 @@ bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t    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 +    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); +      //////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;        }      } -    else{ -      index = 0;  // reset index if any char does not match -    } +          if(termLen > 0 && c == terminator[termIndex]){ -       if(++termIndex >= termLen) -         return false;       // return false if terminate string found before target string +      if(++termIndex >= termLen) +        return false;       // return false if terminate string found before target string      }      else -        termIndex = 0; +      termIndex = 0;    }    return false;  } @@ -242,3 +244,27 @@ size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)    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/cores/arduino/Stream.h b/cores/arduino/Stream.h index 13f11be..58bbf75 100644 --- a/cores/arduino/Stream.h +++ b/cores/arduino/Stream.h @@ -82,6 +82,8 @@ class Stream : public Print    // 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 diff --git a/cores/arduino/USBAPI.h b/cores/arduino/USBAPI.h index 26a2032..eb2e593 100644 --- a/cores/arduino/USBAPI.h +++ b/cores/arduino/USBAPI.h @@ -9,17 +9,17 @@  //================================================================================  //	USB -class USB_ +class USBDevice_  {  public: -	USB_(); +	USBDevice_();  	bool configured();  	void attach();  	void detach();	// Serial port goes down too...  	void poll();  }; -extern USB_ USB; +extern USBDevice_ USBDevice;  //================================================================================  //================================================================================ @@ -27,15 +27,20 @@ extern USB_ USB;  class Serial_ : public Stream  { +private: +	ring_buffer *_cdc_rx_buffer;  public:  	void begin(uint16_t baud_count);  	void end(void);  	virtual int available(void); +	virtual void accept(void);  	virtual int peek(void);  	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; @@ -54,12 +59,14 @@ private:  	uint8_t _buttons;  	void buttons(uint8_t b);  public: -	Mouse_(); +	Mouse_(void); +	void begin(void); +	void end(void);  	void click(uint8_t b = MOUSE_LEFT);  	void move(signed char x, signed char y, signed char wheel = 0);	  	void press(uint8_t b = MOUSE_LEFT);		// press LEFT by default  	void release(uint8_t b = MOUSE_LEFT);	// release LEFT by default -	bool isPressed(uint8_t b = MOUSE_ALL);	// check all buttons by default +	bool isPressed(uint8_t b = MOUSE_LEFT);	// check LEFT by default  };  extern Mouse_ Mouse; @@ -67,14 +74,42 @@ extern Mouse_ Mouse;  //================================================================================  //	Keyboard -#define KEY_MODIFIER_LEFT_CTRL		0x01 -#define KEY_MODIFIER_LEFT_SHIFT		0x02 -#define KEY_MODIFIER_LEFT_ALT		0x04 -#define KEY_MODIFIER_LEFT_GUI		0x08 -#define KEY_MODIFIER_RIGHT_CTRL		0x010 -#define KEY_MODIFIER_RIGHT_SHIFT	0x020 -#define KEY_MODIFIER_RIGHT_ALT		0x040 -#define KEY_MODIFIER_RIGHT_GUI		0x080 +#define KEY_LEFT_CTRL		0x80 +#define KEY_LEFT_SHIFT		0x81 +#define KEY_LEFT_ALT		0x82 +#define KEY_LEFT_GUI		0x83 +#define KEY_RIGHT_CTRL		0x84 +#define KEY_RIGHT_SHIFT		0x85 +#define KEY_RIGHT_ALT		0x86 +#define KEY_RIGHT_GUI		0x87 + +#define KEY_UP_ARROW		0xDA +#define KEY_DOWN_ARROW		0xD9 +#define KEY_LEFT_ARROW		0xD8 +#define KEY_RIGHT_ARROW		0xD7 +#define KEY_BACKSPACE		0xB2 +#define KEY_TAB				0xB3 +#define KEY_RETURN			0xB0 +#define KEY_ESC				0xB1 +#define KEY_INSERT			0xD1 +#define KEY_DELETE			0xD4 +#define KEY_PAGE_UP			0xD3 +#define KEY_PAGE_DOWN		0xD6 +#define KEY_HOME			0xD2 +#define KEY_END				0xD5 +#define KEY_CAPS_LOCK		0xC1 +#define KEY_F1				0xC2 +#define KEY_F2				0xC3 +#define KEY_F3				0xC4 +#define KEY_F4				0xC5 +#define KEY_F5				0xC6 +#define KEY_F6				0xC7 +#define KEY_F7				0xC8 +#define KEY_F8				0xC9 +#define KEY_F9				0xCA +#define KEY_F10				0xCB +#define KEY_F11				0xCC +#define KEY_F12				0xCD  //	Low level key report: up to 6 keys and shift, ctrl etc at once  typedef struct @@ -84,24 +119,19 @@ typedef struct  	uint8_t keys[6];  } KeyReport; -//	Map a character into a key report -//	Called from Print to map text to keycodes -class KeyMap -{ -public: -	virtual void charToKey(int c, KeyReport* keyReport) = 0; -}; - -//	  class Keyboard_ : public Print  {  private: -	KeyMap* _keyMap; +	KeyReport _keyReport;  	void sendReport(KeyReport* keys); -	void setKeyMap(KeyMap* keyMap);	  public: -	Keyboard_(); -	virtual size_t write(uint8_t); +	Keyboard_(void); +	void begin(void); +	void end(void); +	virtual size_t write(uint8_t k); +	virtual size_t press(uint8_t k); +	virtual size_t release(uint8_t k); +	virtual void releaseAll(void);  };  extern Keyboard_ Keyboard; diff --git a/cores/arduino/USBCore.cpp b/cores/arduino/USBCore.cpp index 4c71b34..6766be6 100644 --- a/cores/arduino/USBCore.cpp +++ b/cores/arduino/USBCore.cpp @@ -51,16 +51,20 @@ const u16 STRING_LANGUAGE[2] = {  const u16 STRING_IPRODUCT[17] = {  	(3<<8) | (2+2*16), -#if USB_PID == USB_PID_LEONARDO	 +#if USB_PID == 0x8036	  	'A','r','d','u','i','n','o',' ','L','e','o','n','a','r','d','o' -#elif USB_PID == USB_PID_MICRO -	'A','r','d','u','i','n','o',' ','M','i','c','r','o',' ',' ',' ' +#else +	'U','S','B',' ','I','O',' ','B','o','a','r','d',' ',' ',' ',' '  #endif  };  const u16 STRING_IMANUFACTURER[12] = {  	(3<<8) | (2+2*11), +#if USB_VID == 0x2341  	'A','r','d','u','i','n','o',' ','L','L','C' +#else +	'U','n','k','n','o','w','n',' ',' ',' ',' ' +#endif  };  #ifdef CDC_ENABLED @@ -230,7 +234,7 @@ int USB_Recv(u8 ep, void* d, int len)  	n = len;  	u8* dst = (u8*)d;  	while (n--) -		*dst++ = USBD_Recv8(); +		*dst++ = Recv8();  	if (len && !FifoByteCount())	// release empty buffer  		ReleaseRX(); @@ -599,6 +603,8 @@ ISR(USB_GEN_vect)  	{  #ifdef CDC_ENABLED  		USB_Flush(CDC_TX);				// Send a tx frame if found +		while (USB_Available(CDC_RX))	// Handle received bytes (if any) +			Serial.accept();  #endif  		// check whether the one-shot period has elapsed.  if so, turn off the LED @@ -621,13 +627,13 @@ u8 USBConnected()  //=======================================================================  //======================================================================= -USB_ USB; +USBDevice_ USBDevice; -USB_::USB_() +USBDevice_::USBDevice_()  {  } -void USB_::attach() +void USBDevice_::attach()  {  	_usbConfiguration = 0;  	UHWCON = 0x01;						// power internal reg @@ -635,6 +641,12 @@ void USB_::attach()  	PLLCSR = 0x12;						// Need 16 MHz xtal  	while (!(PLLCSR & (1<<PLOCK)))		// wait for lock pll  		; + +	// Some tests on specific versions of macosx (10.7.3), reported some +	// strange behaviuors when the board is reset using the serial +	// port touch at 1200 bps. This delay fixes this behaviour. +	delay(1); +  	USBCON = ((1<<USBE)|(1<<OTGPADE));	// start USB clock  	UDIEN = (1<<EORSTE)|(1<<SOFE);		// Enable interrupts for EOR (End of Reset) and SOF (start of frame)  	UDCON = 0;							// enable attach resistor @@ -642,19 +654,19 @@ void USB_::attach()  	TX_RX_LED_INIT;  } -void USB_::detach() +void USBDevice_::detach()  {  }  //	Check for interrupts  //	TODO: VBUS detection -bool USB_::configured() +bool USBDevice_::configured()  {  	return _usbConfiguration;  } -void USB_::poll() +void USBDevice_::poll()  {  } -#endif /* if defined(USBCON) */
\ No newline at end of file +#endif /* if defined(USBCON) */ diff --git a/cores/arduino/USBDesc.h b/cores/arduino/USBDesc.h index 549ed9e..900713e 100644 --- a/cores/arduino/USBDesc.h +++ b/cores/arduino/USBDesc.h @@ -60,8 +60,4 @@  #define IMANUFACTURER	1  #define IPRODUCT		2 -#define USB_PID_LEONARDO 0x0034 -#define USB_PID_MICRO 0x0035 -#define USB_VID 0x2341	// arduino LLC vid -#define USB_PID	ARDUINO_MODEL_USB_PID	 diff --git a/cores/arduino/WInterrupts.c b/cores/arduino/WInterrupts.c index 1449cfb..62efc9c 100755..100644 --- a/cores/arduino/WInterrupts.c +++ b/cores/arduino/WInterrupts.c @@ -32,7 +32,7 @@  #include "wiring_private.h" -volatile static voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS]; +static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS];  // volatile static voidFuncPtr twiIntFunc;  void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) { @@ -47,7 +47,27 @@ void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {      // Enable the interrupt.      switch (interruptNum) { -#if defined(EICRA) && defined(EICRB) && defined(EIMSK) +#if defined(__AVR_ATmega32U4__) +	// I hate doing this, but the register assignment differs between the 1280/2560 +	// and the 32U4.  Since avrlib defines registers PCMSK1 and PCMSK2 that aren't  +	// even present on the 32U4 this is the only way to distinguish between them. +	case 0: +		EICRA = (EICRA & ~((1<<ISC00) | (1<<ISC01))) | (mode << ISC00); +		EIMSK |= (1<<INT0); +		break; +	case 1: +		EICRA = (EICRA & ~((1<<ISC10) | (1<<ISC11))) | (mode << ISC10); +		EIMSK |= (1<<INT1); +		break;	 +    case 2: +        EICRA = (EICRA & ~((1<<ISC20) | (1<<ISC21))) | (mode << ISC20); +        EIMSK |= (1<<INT2); +        break; +    case 3: +        EICRA = (EICRA & ~((1<<ISC30) | (1<<ISC31))) | (mode << ISC30); +        EIMSK |= (1<<INT3); +        break; +#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)      case 2:        EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);        EIMSK |= (1 << INT0); @@ -80,7 +100,7 @@ void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {        EICRB = (EICRB & ~((1 << ISC70) | (1 << ISC71))) | (mode << ISC70);        EIMSK |= (1 << INT7);        break; -#else +#else		      case 0:      #if defined(EICRA) && defined(ISC00) && defined(EIMSK)        EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00); @@ -121,8 +141,6 @@ void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {      #elif defined(MCUCR) && defined(ISC20) && defined(GIMSK) && defined(GIMSK)        MCUCR = (MCUCR & ~((1 << ISC20) | (1 << ISC21))) | (mode << ISC20);        GIMSK |= (1 << INT2); -    #else -      #warning attachInterrupt may need some more work for this cpu (case 1)      #endif        break;  #endif @@ -136,7 +154,20 @@ void detachInterrupt(uint8_t interruptNum) {      // to the number of the EIMSK bit to clear, as this isn't true on the       // ATmega8.  There, INT0 is 6 and INT1 is 7.)      switch (interruptNum) { -#if defined(EICRA) && defined(EICRB) && defined(EIMSK) +#if defined(__AVR_ATmega32U4__) +    case 0: +        EIMSK &= ~(1<<INT0); +        break; +    case 1: +        EIMSK &= ~(1<<INT1); +        break; +    case 2: +        EIMSK &= ~(1<<INT2); +        break; +    case 3: +        EIMSK &= ~(1<<INT3); +        break;		 +#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)      case 2:        EIMSK &= ~(1 << INT0);        break; @@ -198,7 +229,28 @@ void attachInterruptTwi(void (*userFunc)(void) ) {  }  */ -#if defined(EICRA) && defined(EICRB) +#if defined(__AVR_ATmega32U4__) +SIGNAL(INT0_vect) { +	if(intFunc[EXTERNAL_INT_0]) +		intFunc[EXTERNAL_INT_0](); +} + +SIGNAL(INT1_vect) { +	if(intFunc[EXTERNAL_INT_1]) +		intFunc[EXTERNAL_INT_1](); +} + +SIGNAL(INT2_vect) { +    if(intFunc[EXTERNAL_INT_2]) +		intFunc[EXTERNAL_INT_2](); +} + +SIGNAL(INT3_vect) { +    if(intFunc[EXTERNAL_INT_3]) +		intFunc[EXTERNAL_INT_3](); +} + +#elif defined(EICRA) && defined(EICRB)  SIGNAL(INT0_vect) {    if(intFunc[EXTERNAL_INT_2]) diff --git a/cores/arduino/WString.cpp b/cores/arduino/WString.cpp index 3e81331..c6839fc 100644 --- a/cores/arduino/WString.cpp +++ b/cores/arduino/WString.cpp @@ -500,7 +500,7 @@ int String::lastIndexOf( char theChar ) const  int String::lastIndexOf(char ch, unsigned int fromIndex) const  { -	if (fromIndex >= len || fromIndex < 0) return -1; +	if (fromIndex >= len) return -1;  	char tempchar = buffer[fromIndex + 1];  	buffer[fromIndex + 1] = '\0';  	char* temp = strrchr( buffer, ch ); @@ -516,7 +516,7 @@ int String::lastIndexOf(const String &s2) const  int String::lastIndexOf(const String &s2, unsigned int fromIndex) const  { -  	if (s2.len == 0 || len == 0 || s2.len > len || fromIndex < 0) return -1; +  	if (s2.len == 0 || len == 0 || s2.len > len) return -1;  	if (fromIndex >= len) fromIndex = len - 1;  	int found = -1;  	for (char *p = buffer; p <= buffer + fromIndex; p++) { diff --git a/cores/arduino/main.cpp b/cores/arduino/main.cpp index 34450f4..3d4e079 100755..100644 --- a/cores/arduino/main.cpp +++ b/cores/arduino/main.cpp @@ -5,7 +5,7 @@ int main(void)  	init();  #if defined(USBCON) -	USB.attach(); +	USBDevice.attach();  #endif  	setup(); diff --git a/cores/arduino/wiring.c b/cores/arduino/wiring.c index e7f7cde..ac8bb6f 100755..100644 --- a/cores/arduino/wiring.c +++ b/cores/arduino/wiring.c @@ -278,12 +278,21 @@ void init()  	sbi(TCCR3B, CS30);  	sbi(TCCR3A, WGM30);		// put timer 3 in 8-bit phase correct pwm mode  #endif -	 + +#if defined(TCCR4A) && defined(TCCR4B) && defined(TCCR4D) /* beginning of timer4 block for 32U4 and similar */ +	sbi(TCCR4B, CS42);		// set timer4 prescale factor to 64 +	sbi(TCCR4B, CS41); +	sbi(TCCR4B, CS40); +	sbi(TCCR4D, WGM40);		// put timer 4 in phase- and frequency-correct PWM mode	 +	sbi(TCCR4A, PWM4A);		// enable PWM mode for comparator OCR4A +	sbi(TCCR4C, PWM4D);		// enable PWM mode for comparator OCR4D +#else /* beginning of timer4 block for ATMEGA1280 and ATMEGA2560 */  #if defined(TCCR4B) && defined(CS41) && defined(WGM40)  	sbi(TCCR4B, CS41);		// set timer 4 prescale factor to 64  	sbi(TCCR4B, CS40);  	sbi(TCCR4A, WGM40);		// put timer 4 in 8-bit phase correct pwm mode  #endif +#endif /* end timer4 block for ATMEGA1280/2560 and similar */	  #if defined(TCCR5B) && defined(CS51) && defined(WGM50)  	sbi(TCCR5B, CS51);		// set timer 5 prescale factor to 64 diff --git a/cores/arduino/wiring_analog.c b/cores/arduino/wiring_analog.c index 902b153..0e9881f 100644 --- a/cores/arduino/wiring_analog.c +++ b/cores/arduino/wiring_analog.c @@ -45,6 +45,8 @@ int analogRead(uint8_t pin)  	if (pin >= 54) pin -= 54; // allow for channel or pin numbers  #elif defined(__AVR_ATmega32U4__)  	if (pin >= 18) pin -= 18; // allow for channel or pin numbers +#elif defined(__AVR_ATmega1284__) +	if (pin >= 24) pin -= 24; // allow for channel or pin numbers  #else  	if (pin >= 14) pin -= 14; // allow for channel or pin numbers  #endif @@ -204,14 +206,17 @@ void analogWrite(uint8_t pin, int val)  				break;  			#endif -			#if defined(TCCR4A) && defined(COM4A1) +			#if defined(TCCR4A)  			case TIMER4A: -				// connect pwm to pin on timer 4, channel A +				//connect pwm to pin on timer 4, channel A  				sbi(TCCR4A, COM4A1); -				OCR4A = val; // set pwm duty +				#if defined(COM4A0)		// only used on 32U4 +				cbi(TCCR4A, COM4A0); +				#endif +				OCR4A = val;	// set pwm duty  				break;  			#endif - +			  			#if defined(TCCR4A) && defined(COM4B1)  			case TIMER4B:  				// connect pwm to pin on timer 4, channel B @@ -228,14 +233,18 @@ void analogWrite(uint8_t pin, int val)  				break;  			#endif -			#if defined(TCCR4A) && defined(COM4D1) -			case TIMER4D: +			#if defined(TCCR4C) && defined(COM4D1) +			case TIMER4D:				  				// connect pwm to pin on timer 4, channel D -				sbi(TCCR4A, COM4D1); -				OCR4D = val; // set pwm duty +				sbi(TCCR4C, COM4D1); +				#if defined(COM4D0)		// only used on 32U4 +				cbi(TCCR4C, COM4D0); +				#endif +				OCR4D = val;	// set pwm duty  				break;  			#endif +							  			#if defined(TCCR5A) && defined(COM5A1)  			case TIMER5A:  				// connect pwm to pin on timer 5, channel A @@ -270,3 +279,4 @@ void analogWrite(uint8_t pin, int val)  		}  	}  } + diff --git a/cores/arduino/wiring_digital.c b/cores/arduino/wiring_digital.c index 97ef134..be323b1 100755..100644 --- a/cores/arduino/wiring_digital.c +++ b/cores/arduino/wiring_digital.c @@ -32,17 +32,25 @@ void pinMode(uint8_t pin, uint8_t mode)  {  	uint8_t bit = digitalPinToBitMask(pin);  	uint8_t port = digitalPinToPort(pin); -	volatile uint8_t *reg; +	volatile uint8_t *reg, *out;  	if (port == NOT_A_PIN) return;  	// JWS: can I let the optimizer do this?  	reg = portModeRegister(port); +	out = portOutputRegister(port);  	if (mode == INPUT) {   		uint8_t oldSREG = SREG;                  cli();  		*reg &= ~bit; +		*out &= ~bit; +		SREG = oldSREG; +	} else if (mode == INPUT_PULLUP) { +		uint8_t oldSREG = SREG; +                cli(); +		*reg &= ~bit; +		*out |= bit;  		SREG = oldSREG;  	} else {  		uint8_t oldSREG = SREG; @@ -107,13 +115,17 @@ static void turnOffPWM(uint8_t timer)  		#if defined(TCCR4A) && defined(COM4A1)  		case  TIMER4A:  cbi(TCCR4A, COM4A1);    break; -		#endif +		#endif					  		#if defined(TCCR4A) && defined(COM4B1)  		case  TIMER4B:  cbi(TCCR4A, COM4B1);    break;  		#endif  		#if defined(TCCR4A) && defined(COM4C1)  		case  TIMER4C:  cbi(TCCR4A, COM4C1);    break; -		#endif +		#endif			 +		#if defined(TCCR4C) && defined(COM4D1) +		case TIMER4D:	cbi(TCCR4C, COM4D1);	break; +		#endif			 +			  		#if defined(TCCR5A)  		case  TIMER5A:  cbi(TCCR5A, COM5A1);    break;  		case  TIMER5B:  cbi(TCCR5A, COM5B1);    break; diff --git a/cores/arduino/wiring_private.h b/cores/arduino/wiring_private.h index f0ceb0c..026ce1a 100755 --- a/cores/arduino/wiring_private.h +++ b/cores/arduino/wiring_private.h @@ -56,6 +56,8 @@ extern "C"{  #define EXTERNAL_NUM_INTERRUPTS 8  #elif defined(__AVR_ATmega1284P__)   #define EXTERNAL_NUM_INTERRUPTS 3 +#elif defined(__AVR_ATmega32U4__) +#define EXTERNAL_NUM_INTERRUPTS 4  #else  #define EXTERNAL_NUM_INTERRUPTS 2  #endif | 
