diff options
Diffstat (limited to 'cores')
| -rwxr-xr-x | cores/arduino/Arduino.h | 7 | ||||
| -rw-r--r-- | cores/arduino/CDC.cpp | 175 | ||||
| -rw-r--r-- | cores/arduino/HID.cpp | 446 | ||||
| -rw-r--r-- | cores/arduino/HardwareSerial.cpp | 18 | ||||
| -rw-r--r-- | cores/arduino/HardwareSerial.h | 3 | ||||
| -rw-r--r-- | cores/arduino/Platform.h | 23 | ||||
| -rwxr-xr-x | cores/arduino/Print.cpp | 2 | ||||
| -rw-r--r-- | cores/arduino/Stream.cpp | 9 | ||||
| -rw-r--r-- | cores/arduino/Stream.h | 6 | ||||
| -rw-r--r-- | cores/arduino/USBAPI.h | 166 | ||||
| -rw-r--r-- | cores/arduino/USBCore.cpp | 660 | ||||
| -rw-r--r-- | cores/arduino/USBCore.h | 303 | ||||
| -rw-r--r-- | cores/arduino/USBDesc.h | 67 | ||||
| -rw-r--r-- | cores/arduino/WString.cpp | 6 | ||||
| -rw-r--r-- | cores/arduino/WString.h | 4 | ||||
| -rwxr-xr-x | cores/arduino/main.cpp | 4 | ||||
| -rwxr-xr-x | cores/arduino/wiring.c | 4 | ||||
| -rw-r--r-- | cores/arduino/wiring_analog.c | 15 | ||||
| -rwxr-xr-x | cores/arduino/wiring_private.h | 1 | 
19 files changed, 1895 insertions, 24 deletions
| diff --git a/cores/arduino/Arduino.h b/cores/arduino/Arduino.h index ebdbe9a..7f2fc05 100755 --- a/cores/arduino/Arduino.h +++ b/cores/arduino/Arduino.h @@ -169,9 +169,10 @@ extern const uint8_t PROGMEM digital_pin_to_timer_PGM[];  #define TIMER4A 11  #define TIMER4B 12  #define TIMER4C 13 -#define TIMER5A 14 -#define TIMER5B 15 -#define TIMER5C 16 +#define TIMER4D 14	 +#define TIMER5A 15 +#define TIMER5B 16 +#define TIMER5C 17  #ifdef __cplusplus  } // extern "C" diff --git a/cores/arduino/CDC.cpp b/cores/arduino/CDC.cpp new file mode 100644 index 0000000..14a0eae --- /dev/null +++ b/cores/arduino/CDC.cpp @@ -0,0 +1,175 @@ + + +/* 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.   +*/ + +#include "Platform.h" +#include "USBAPI.h" +#include <avr/wdt.h> + +#if defined(USBCON) +#ifdef CDC_ENABLED + +void Reboot() +{ +	USB.detach(); +	cli(); +	asm volatile("jmp 0x7800");		// jump to bootloader - DiskLoader takes up last 2 kB +} + +typedef struct +{ +	u32	dwDTERate; +	u8	bCharFormat; +	u8 	bParityType; +	u8 	bDataBits; +	u8	lineState; +} LineInfo; + +static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 }; + +#define WEAK __attribute__ ((weak)) + +extern const CDCDescriptor _cdcInterface PROGMEM; +const CDCDescriptor _cdcInterface = +{ +	D_IAD(0,2,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,1), + +	//	CDC communication interface +	D_INTERFACE(CDC_ACM_INTERFACE,1,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0), +	D_CDCCS(CDC_HEADER,0x10,0x01),								// Header (1.10 bcd) +	D_CDCCS(CDC_CALL_MANAGEMENT,1,1),							// Device handles call management (not) +	D_CDCCS4(CDC_ABSTRACT_CONTROL_MANAGEMENT,6),				// SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported +	D_CDCCS(CDC_UNION,CDC_ACM_INTERFACE,CDC_DATA_INTERFACE),	// Communication interface is master, data interface is slave 0 +	D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_ACM),USB_ENDPOINT_TYPE_INTERRUPT,0x10,0x40), + +	//	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) +}; + +int WEAK CDC_GetInterface(u8* interfaceNum) +{ +	interfaceNum[0] += 2;	// uses 2 +	return USB_SendControl(TRANSFER_PGM,&_cdcInterface,sizeof(_cdcInterface)); +} + +bool WEAK CDC_Setup(Setup& setup) +{ +	u8 r = setup.bRequest; +	u8 requestType = setup.bmRequestType; + +	if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType) +	{ +		if (CDC_GET_LINE_CODING == r) +		{ +			USB_SendControl(0,(void*)&_usbLineInfo,7); +			return true; +		} +	} + +	if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType) +	{ +		if (CDC_SET_LINE_CODING == r) +		{ +			USB_RecvControl((void*)&_usbLineInfo,7); +			return true; +		} + +		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; +			return true; +		} +	} +	return false; +} + + +int _serialPeek = -1; +void Serial_::begin(uint16_t baud_count) +{ +} + +void Serial_::end(void) +{ +} + +int Serial_::available(void) +{ +	u8 avail = USB_Available(CDC_RX); +	if (_serialPeek != -1) +		avail++; +	return avail; +} + +//	peek is nasty +int Serial_::peek(void) +{ +	if (_serialPeek == -1) +		_serialPeek = read(); +	return _serialPeek; +} + +int Serial_::read(void) +{ +	int c; +	if (_serialPeek != -1) +	{ +		c = _serialPeek; +		_serialPeek = -1; +	} else { +		c = USB_Recv(CDC_RX); +	} +	return c; +} + +void Serial_::flush(void) +{ +	USB_Flush(CDC_TX); +} + +size_t Serial_::write(uint8_t c) +{ +	/* only try to send bytes if the high-level CDC connection itself  +	 is open (not just the pipe) - the OS should set lineState when the port +	 is opened and clear lineState when the port is closed. +	 bytes sent before the user opens the connection or after +	 the connection is closed are lost - just like with a UART. */ +	 +	// TODO - ZE - check behavior on different OSes and test what happens if an +	// open connection isn't broken cleanly (cable is yanked out, host dies +	// or locks up, or host virtual serial port hangs) +	if (_usbLineInfo.lineState > 0)	{ +		int r = USB_Send(CDC_TX,&c,1); +		if (r > 0) { +			return r; +		} else { +			setWriteError(); +			return 0; +		} +	} +	setWriteError(); +	return 0; +} + +Serial_ Serial; + +#endif +#endif /* if defined(USBCON) */
\ No newline at end of file diff --git a/cores/arduino/HID.cpp b/cores/arduino/HID.cpp new file mode 100644 index 0000000..8ed1566 --- /dev/null +++ b/cores/arduino/HID.cpp @@ -0,0 +1,446 @@ + + +/* 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.   +*/ + +#include "Platform.h" +#include "USBAPI.h" +#include "USBDesc.h" + +#if defined(USBCON) +#ifdef HID_ENABLED + +//#define RAWHID_ENABLED + +//	Singletons for mouse and keyboard + +Mouse_ Mouse; +Keyboard_ Keyboard; + +//================================================================================ +//================================================================================ + +//	HID report descriptor + +#define LSB(_x) ((_x) & 0xFF) +#define MSB(_x) ((_x) >> 8) + +#define RAWHID_USAGE_PAGE	0xFFC0 +#define RAWHID_USAGE		0x0C00 +#define RAWHID_TX_SIZE 64 +#define RAWHID_RX_SIZE 64 + +extern const u8 _hidReportDescriptor[] PROGMEM; +const u8 _hidReportDescriptor[] = { +	 +	//	Mouse +    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)	// 54 +    0x09, 0x02,                    // USAGE (Mouse) +    0xa1, 0x01,                    // COLLECTION (Application) +    0x09, 0x01,                    //   USAGE (Pointer) +    0xa1, 0x00,                    //   COLLECTION (Physical) +    0x85, 0x01,                    //     REPORT_ID (1) +    0x05, 0x09,                    //     USAGE_PAGE (Button) +    0x19, 0x01,                    //     USAGE_MINIMUM (Button 1) +    0x29, 0x03,                    //     USAGE_MAXIMUM (Button 3) +    0x15, 0x00,                    //     LOGICAL_MINIMUM (0) +    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1) +    0x95, 0x03,                    //     REPORT_COUNT (3) +    0x75, 0x01,                    //     REPORT_SIZE (1) +    0x81, 0x02,                    //     INPUT (Data,Var,Abs) +    0x95, 0x01,                    //     REPORT_COUNT (1) +    0x75, 0x05,                    //     REPORT_SIZE (5) +    0x81, 0x03,                    //     INPUT (Cnst,Var,Abs) +    0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop) +    0x09, 0x30,                    //     USAGE (X) +    0x09, 0x31,                    //     USAGE (Y) +    0x09, 0x38,                    //     USAGE (Wheel) +    0x15, 0x81,                    //     LOGICAL_MINIMUM (-127) +    0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127) +    0x75, 0x08,                    //     REPORT_SIZE (8) +    0x95, 0x03,                    //     REPORT_COUNT (3) +    0x81, 0x06,                    //     INPUT (Data,Var,Rel) +    0xc0,                          //   END_COLLECTION +    0xc0,                          // END_COLLECTION + +	//	Keyboard +    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)	// 47 +    0x09, 0x06,                    // USAGE (Keyboard) +    0xa1, 0x01,                    // COLLECTION (Application) +    0x85, 0x02,                    //   REPORT_ID (2) +    0x05, 0x07,                    //   USAGE_PAGE (Keyboard) +    +	0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl) +    0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI) +    0x15, 0x00,                    //   LOGICAL_MINIMUM (0) +    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1) +    0x75, 0x01,                    //   REPORT_SIZE (1) +     +	0x95, 0x08,                    //   REPORT_COUNT (8) +    0x81, 0x02,                    //   INPUT (Data,Var,Abs) +    0x95, 0x01,                    //   REPORT_COUNT (1) +    0x75, 0x08,                    //   REPORT_SIZE (8) +    0x81, 0x03,                    //   INPUT (Cnst,Var,Abs) +     +	0x95, 0x06,                    //   REPORT_COUNT (6) +    0x75, 0x08,                    //   REPORT_SIZE (8) +    0x15, 0x00,                    //   LOGICAL_MINIMUM (0) +    0x25, 0x65,                    //   LOGICAL_MAXIMUM (101) +    0x05, 0x07,                    //   USAGE_PAGE (Keyboard) +     +	0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated)) +    0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application) +    0x81, 0x00,                    //   INPUT (Data,Ary,Abs) +    0xc0,                          // END_COLLECTION + +#if RAWHID_ENABLED +	//	RAW HID +	0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE),	// 30 +	0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE), + +	0xA1, 0x01,				// Collection 0x01 +    0x85, 0x03,             // REPORT_ID (3) +	0x75, 0x08,				// report size = 8 bits +	0x15, 0x00,				// logical minimum = 0 +	0x26, 0xFF, 0x00,		// logical maximum = 255 + +	0x95, 64,				// report count TX +	0x09, 0x01,				// usage +	0x81, 0x02,				// Input (array) + +	0x95, 64,				// report count RX +	0x09, 0x02,				// usage +	0x91, 0x02,				// Output (array) +	0xC0					// end collection +#endif +}; + +extern const HIDDescriptor _hidInterface PROGMEM; +const HIDDescriptor _hidInterface = +{ +	D_INTERFACE(HID_INTERFACE,1,3,0,0), +	D_HIDREPORT(sizeof(_hidReportDescriptor)), +	D_ENDPOINT(USB_ENDPOINT_IN (HID_ENDPOINT_INT),USB_ENDPOINT_TYPE_INTERRUPT,0x40,0x01) +}; + +//================================================================================ +//================================================================================ +//	Driver + +u8 _hid_protocol = 1; +u8 _hid_idle = 1; + +#define WEAK __attribute__ ((weak)) +#define WEAK  + +int WEAK HID_GetInterface(u8* interfaceNum) +{ +	interfaceNum[0] += 1;	// uses 1 +	return USB_SendControl(TRANSFER_PGM,&_hidInterface,sizeof(_hidInterface)); +} + +int WEAK HID_GetDescriptor(int i) +{ +	return USB_SendControl(TRANSFER_PGM,_hidReportDescriptor,sizeof(_hidReportDescriptor)); +} + +void WEAK HID_SendReport(u8 id, const void* data, int len) +{ +	USB_Send(HID_TX, &id, 1); +	USB_Send(HID_TX | TRANSFER_RELEASE,data,len); +} + +bool WEAK HID_Setup(Setup& setup) +{ +	u8 r = setup.bRequest; +	u8 requestType = setup.bmRequestType; +	if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType) +	{ +		if (HID_GET_REPORT == r) +		{ +			//HID_GetReport(); +			return true; +		} +		if (HID_GET_PROTOCOL == r) +		{ +			//Send8(_hid_protocol);	// TODO +			return true; +		} +	} +	 +	if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType) +	{ +		if (HID_SET_PROTOCOL == r) +		{ +			_hid_protocol = setup.wValueL; +			return true; +		} + +		if (HID_SET_IDLE == r) +		{ +			_hid_idle = setup.wValueL; +			return true; +		} +	} +	return false; +} + +//================================================================================ +//================================================================================ +//	Mouse + +Mouse_::Mouse_() : _buttons(0) +{ +} + +void Mouse_::click(uint8_t b) +{ +	_buttons = b; +	move(0,0,0); +	_buttons = 0; +	move(0,0,0); +} + +void Mouse_::move(signed char x, signed char y, signed char wheel) +{ +	u8 m[4]; +	m[0] = _buttons; +	m[1] = x; +	m[2] = y; +	m[3] = wheel; +	HID_SendReport(1,m,4); +} + +void Mouse_::buttons(uint8_t b) +{ +	if (b != _buttons) +	{ +		_buttons = b; +		move(0,0,0); +	} +} + +void Mouse_::press(uint8_t b)  +{ +	buttons(_buttons | b); +} + +void Mouse_::release(uint8_t b) +{ +	buttons(_buttons & ~b); +} + +bool Mouse_::isPressed(uint8_t b) +{ +	if (b & _buttons > 0)  +		return true; +	return false; +} + +//================================================================================ +//================================================================================ +//	Keyboard + +Keyboard_::Keyboard_() : _keyMap(0) +{ +} + +void Keyboard_::sendReport(KeyReport* keys) +{ +	HID_SendReport(2,keys,sizeof(KeyReport)); +} + +void Keyboard_::setKeyMap(KeyMap* keyMap) +{ +	_keyMap = keyMap; +} + +extern +const uint8_t _asciimap[128] PROGMEM; + +#define SHIFT 0x80 +const uint8_t _asciimap[128] = +{ +	0x00,             // NUL +	0x00,             // SOH +	0x00,             // STX +	0x00,             // ETX +	0x00,             // EOT +	0x00,             // ENQ +	0x00,             // ACK   +	0x00,             // BEL +	0x2a,			// BS	Backspace +	0x2b,			// TAB	Tab +	0x28,			// LF	Enter +	0x00,             // VT  +	0x00,             // FF  +	0x00,             // CR  +	0x00,             // SO  +	0x00,             // SI  +	0x00,             // DEL +	0x00,             // DC1 +	0x00,             // DC2 +	0x00,             // DC3 +	0x00,             // DC4 +	0x00,             // NAK +	0x00,             // SYN +	0x00,             // ETB +	0x00,             // CAN +	0x00,             // EM  +	0x00,             // SUB +	0x00,             // ESC +	0x00,             // FS  +	0x00,             // GS  +	0x00,             // RS  +	0x00,             // US  + +	0x2c,		   //  ' ' +	0x1e|SHIFT,	   // ! +	0x34|SHIFT,	   // " +	0x20|SHIFT,    // # +	0x21|SHIFT,    // $ +	0x22|SHIFT,    // % +	0x24|SHIFT,    // & +	0x34,          // ' +	0x26|SHIFT,    // ( +	0x27|SHIFT,    // ) +	0x25|SHIFT,    // * +	0x2e|SHIFT,    // + +	0x36,          // , +	0x2d,          // - +	0x37,          // . +	0x38,          // / +	0x27,          // 0 +	0x1e,          // 1 +	0x1f,          // 2 +	0x20,          // 3 +	0x21,          // 4 +	0x22,          // 5 +	0x23,          // 6 +	0x24,          // 7 +	0x25,          // 8 +	0x26,          // 9 +	0x33|SHIFT,      // : +	0x33,          // ; +	0x36|SHIFT,      // < +	0x2e,          // = +	0x37|SHIFT,      // > +	0x38|SHIFT,      // ? +	0x1f|SHIFT,      // @ +	0x04|SHIFT,      // A +	0x05|SHIFT,      // B +	0x06|SHIFT,      // C +	0x07|SHIFT,      // D +	0x08|SHIFT,      // E +	0x09|SHIFT,      // F +	0x0a|SHIFT,      // G +	0x0b|SHIFT,      // H +	0x0c|SHIFT,      // I +	0x0d|SHIFT,      // J +	0x0e|SHIFT,      // K +	0x0f|SHIFT,      // L +	0x10|SHIFT,      // M +	0x11|SHIFT,      // N +	0x12|SHIFT,      // O +	0x13|SHIFT,      // P +	0x14|SHIFT,      // Q +	0x15|SHIFT,      // R +	0x16|SHIFT,      // S +	0x17|SHIFT,      // T +	0x18|SHIFT,      // U +	0x19|SHIFT,      // V +	0x1a|SHIFT,      // W +	0x1b|SHIFT,      // X +	0x1c|SHIFT,      // Y +	0x1d|SHIFT,      // Z +	0x2f,          // [ +	0x31,          // bslash +	0x30,          // ] +	0x23|SHIFT,    // ^ +	0x2d|SHIFT,    // _ +	0x35,          // ` +	0x04,          // a +	0x05,          // b +	0x06,          // c +	0x07,          // d +	0x08,          // e +	0x09,          // f +	0x0a,          // g +	0x0b,          // h +	0x0c,          // i +	0x0d,          // j +	0x0e,          // k +	0x0f,          // l +	0x10,          // m +	0x11,          // n +	0x12,          // o +	0x13,          // p +	0x14,          // q +	0x15,          // r +	0x16,          // s +	0x17,          // t +	0x18,          // u +	0x19,          // v +	0x1a,          // w +	0x1b,          // x +	0x1c,          // y +	0x1d,          // z +	0x2f|SHIFT,    //  +	0x31|SHIFT,    // | +	0x30|SHIFT,    // } +	0x35|SHIFT,    // ~ +	0				// DEL +}; + +uint8_t USBPutChar(uint8_t c); +size_t Keyboard_::write(uint8_t c) +{ +	// 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; +			} +			keys.keys[0] = c; +		} +		sendReport(&keys); +	} +	//	Keyup +	{ +		KeyReport keys = {0}; +		sendReport(&keys); +	} +	return 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 49a3796..1b1fa71 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -50,6 +50,10 @@ struct ring_buffer    volatile int tail;  }; +#if defined(USBCON) +  ring_buffer rx_buffer = { { 0 }, 0, 0}; +  ring_buffer tx_buffer = { { 0 }, 0, 0}; +#endif  #if defined(UBRRH) || defined(UBRR0H)    ring_buffer rx_buffer  =  { { 0 }, 0, 0 };    ring_buffer tx_buffer  =  { { 0 }, 0, 0 }; @@ -81,10 +85,13 @@ inline void store_char(unsigned char c, ring_buffer *buffer)    }  } +#if !defined(USART0_RX_vect) && defined(USART1_RX_vect) +// do nothing - on the 32u4 the first USART is USART1 +#else  #if !defined(USART_RX_vect) && !defined(SIG_USART0_RECV) && \      !defined(SIG_UART0_RECV) && !defined(USART0_RX_vect) && \  	!defined(SIG_UART_RECV) -  #error Don't know what the Data Received vector is called for the first UART +  #error "Don't know what the Data Received vector is called for the first UART"  #else    void serialEvent() __attribute__((weak));    void serialEvent() {} @@ -111,6 +118,7 @@ inline void store_char(unsigned char c, ring_buffer *buffer)      store_char(c, &rx_buffer);    }  #endif +#endif  #if defined(USART1_RX_vect)    void serialEvent1() __attribute__((weak)); @@ -168,8 +176,11 @@ void serialEventRun(void)  } +#if !defined(USART0_UDRE_vect) && defined(USART1_UDRE_vect) +// do nothing - on the 32u4 the first USART is USART1 +#else  #if !defined(UART0_UDRE_vect) && !defined(UART_UDRE_vect) && !defined(USART0_UDRE_vect) && !defined(USART_UDRE_vect) -  #error Don't know what the Data Register Empty vector is called for the first UART +  #error "Don't know what the Data Register Empty vector is called for the first UART"  #else  #if defined(UART0_UDRE_vect)  ISR(UART0_UDRE_vect) @@ -204,6 +215,7 @@ ISR(USART_UDRE_vect)    }  }  #endif +#endif  #ifdef USART1_UDRE_vect  ISR(USART1_UDRE_vect) @@ -393,7 +405,7 @@ size_t HardwareSerial::write(uint8_t c)  #elif defined(UBRR0H) && defined(UBRR0L)    HardwareSerial Serial(&rx_buffer, &tx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRIE0, U2X0);  #elif defined(USBCON) -  #warning no serial port defined  (port 0) +  // do nothing - Serial object and buffers are initialized in CDC code  #else    #error no serial port defined  (port 0)  #endif diff --git a/cores/arduino/HardwareSerial.h b/cores/arduino/HardwareSerial.h index 1c755f7..176abe1 100644 --- a/cores/arduino/HardwareSerial.h +++ b/cores/arduino/HardwareSerial.h @@ -62,7 +62,8 @@ class HardwareSerial : public Stream  #if defined(UBRRH) || defined(UBRR0H)    extern HardwareSerial Serial;  #elif defined(USBCON) -  #include "usb_api.h" +  #include "USBAPI.h" +//  extern HardwareSerial Serial_;    #endif  #if defined(UBRR1H)    extern HardwareSerial Serial1; diff --git a/cores/arduino/Platform.h b/cores/arduino/Platform.h new file mode 100644 index 0000000..8b8f742 --- /dev/null +++ b/cores/arduino/Platform.h @@ -0,0 +1,23 @@ + +#ifndef __PLATFORM_H__ +#define __PLATFORM_H__ + +#include <inttypes.h> +#include <avr/pgmspace.h> +#include <avr/eeprom.h> +#include <avr/interrupt.h> +#include <util/delay.h> + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; + +#include "Arduino.h" + +#if defined(USBCON) +	#include "USBDesc.h" +	#include "USBCore.h" +	#include "USBAPI.h" +#endif /* if defined(USBCON) */ + +#endif diff --git a/cores/arduino/Print.cpp b/cores/arduino/Print.cpp index 500de8c..ff9b154 100755 --- a/cores/arduino/Print.cpp +++ b/cores/arduino/Print.cpp @@ -54,7 +54,7 @@ size_t Print::print(const __FlashStringHelper *ifsh)  size_t Print::print(const String &s)  {    size_t n = 0; -  for (int i = 0; i < s.length(); i++) { +  for (uint16_t i = 0; i < s.length(); i++) {      n += write(s[i]);    }    return n; diff --git a/cores/arduino/Stream.cpp b/cores/arduino/Stream.cpp index 8b6f1e8..a7d9d38 100644 --- a/cores/arduino/Stream.cpp +++ b/cores/arduino/Stream.cpp @@ -67,9 +67,9 @@ int Stream::peekNextDigit()  // Public Methods  ////////////////////////////////////////////////////////////// -void Stream::setTimeout( long timeout)  // sets the maximum number of milliseconds to wait +void Stream::setTimeout(unsigned long timeout)  // sets the maximum number of milliseconds to wait  { -   this->_timeout = timeout; +  _timeout = timeout;  }   // find returns true if the target string is found @@ -165,7 +165,7 @@ long Stream::parseInt(char skipChar)  // as parseInt but returns a floating point value  float Stream::parseFloat()  { -  parseFloat(NO_SKIP_CHAR); +  return parseFloat(NO_SKIP_CHAR);  }  // as above but the given skipChar is ignored @@ -174,7 +174,6 @@ float Stream::parseFloat(char skipChar){    boolean isNegative = false;    boolean isFraction = false;    long value = 0; -  float fValue;    char c;    float fraction = 1.0; @@ -223,7 +222,7 @@ int Stream::readBytes( char *buffer, size_t length)  int Stream::readBytesUntil( char terminator, char *buffer, size_t length)  { - int index = 0; +    unsigned int index = 0;      *buffer = 0;      while(index < length-1 ){        int c = timedRead(); diff --git a/cores/arduino/Stream.h b/cores/arduino/Stream.h index 3c6d025..8f2de1e 100644 --- a/cores/arduino/Stream.h +++ b/cores/arduino/Stream.h @@ -38,8 +38,8 @@ readBytesBetween( pre_string, terminator, buffer, length)  class Stream : public Print  {    private: -    long _timeout;      // number of milliseconds to wait for the next char before aborting timed read -    long _startMillis;  // used for timeout measurement +    unsigned long _timeout;      // number of milliseconds to wait for the next char before aborting timed read +    unsigned long _startMillis;  // used for timeout measurement      int timedRead();    // private method to read stream with timeout      int timedPeek();    // private method to peek stream with timeout      int peekNextDigit(); // returns the next numeric digit in the stream or -1 if timeout @@ -54,7 +54,7 @@ class Stream : public Print  // parsing methods -  void setTimeout(long timeout);  // sets maximum milliseconds to wait for stream data, default is 1 second +  void setTimeout(unsigned long timeout);  // sets maximum milliseconds to wait for stream data, default is 1 second    bool find(char *target);   // reads data from the stream until the target string is found    // returns true if target string is found, false if timed out (see setTimeout) diff --git a/cores/arduino/USBAPI.h b/cores/arduino/USBAPI.h new file mode 100644 index 0000000..26a2032 --- /dev/null +++ b/cores/arduino/USBAPI.h @@ -0,0 +1,166 @@ + + +#ifndef __USBAPI__ +#define __USBAPI__ + +#if defined(USBCON) + +//================================================================================ +//================================================================================ +//	USB + +class USB_ +{ +public: +	USB_(); +	bool configured(); + +	void attach(); +	void detach();	// Serial port goes down too... +	void poll(); +}; +extern USB_ USB; + +//================================================================================ +//================================================================================ +//	Serial over CDC (Serial1 is the physical port) + +class Serial_ : public Stream +{ +public: +	void begin(uint16_t baud_count); +	void end(void); + +	virtual int available(void); +	virtual int peek(void); +	virtual int read(void); +	virtual void flush(void); +	virtual size_t write(uint8_t); +}; +extern Serial_ Serial; + +//================================================================================ +//================================================================================ +//	Mouse + +#define MOUSE_LEFT 1 +#define MOUSE_RIGHT 2 +#define MOUSE_MIDDLE 4 +#define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE) + +class Mouse_ +{ +private: +	uint8_t _buttons; +	void buttons(uint8_t b); +public: +	Mouse_(); +	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 +}; +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 + +//	Low level key report: up to 6 keys and shift, ctrl etc at once +typedef struct +{ +	uint8_t modifiers; +	uint8_t reserved; +	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; +	void sendReport(KeyReport* keys); +	void setKeyMap(KeyMap* keyMap);	 +public: +	Keyboard_(); +	virtual size_t write(uint8_t); +}; +extern Keyboard_ Keyboard; + +//================================================================================ +//================================================================================ +//	Low level API + +typedef struct +{ +	uint8_t bmRequestType; +	uint8_t bRequest; +	uint8_t wValueL; +	uint8_t wValueH; +	uint16_t wIndex; +	uint16_t wLength; +} Setup; + +//================================================================================ +//================================================================================ +//	HID 'Driver' + +int		HID_GetInterface(uint8_t* interfaceNum); +int		HID_GetDescriptor(int i); +bool	HID_Setup(Setup& setup); +void	HID_SendReport(uint8_t id, const void* data, int len); + +//================================================================================ +//================================================================================ +//	MSC 'Driver' + +int		MSC_GetInterface(uint8_t* interfaceNum); +int		MSC_GetDescriptor(int i); +bool	MSC_Setup(Setup& setup); +bool	MSC_Data(uint8_t rx,uint8_t tx); + +//================================================================================ +//================================================================================ +//	CSC 'Driver' + +int		CDC_GetInterface(uint8_t* interfaceNum); +int		CDC_GetDescriptor(int i); +bool	CDC_Setup(Setup& setup); + +//================================================================================ +//================================================================================ + +#define TRANSFER_PGM		0x80 +#define TRANSFER_RELEASE	0x40 +#define TRANSFER_ZERO		0x20 + +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); +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 +void USB_Flush(uint8_t ep); + +#endif + +#endif /* if defined(USBCON) */
\ No newline at end of file diff --git a/cores/arduino/USBCore.cpp b/cores/arduino/USBCore.cpp new file mode 100644 index 0000000..398bc73 --- /dev/null +++ b/cores/arduino/USBCore.cpp @@ -0,0 +1,660 @@ + + +/* Copyright (c) 2010, 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.   +*/ + +#include "Platform.h" +#include "USBAPI.h" +#include "USBDesc.h" + +#if defined(USBCON) + +#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 + +/** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */ +#define TX_RX_LED_PULSE_MS 100 +volatile u8 TxLEDPulse; /**< Milliseconds remaining for data Tx LED pulse */ +volatile u8 RxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */ + +//================================================================== +//================================================================== + +extern const u16 STRING_LANGUAGE[] PROGMEM; +extern const u16 STRING_IPRODUCT[] PROGMEM; +extern const u16 STRING_IMANUFACTURER[] PROGMEM; +extern const DeviceDescriptor USB_DeviceDescriptor PROGMEM; +extern const DeviceDescriptor USB_DeviceDescriptorA PROGMEM; + +const u16 STRING_LANGUAGE[2] = { +	(3<<8) | (2+2), +	0x0409	// English +}; + +const u16 STRING_IPRODUCT[17] = { +	(3<<8) | (2+2*16), +#if USB_PID == USB_PID_LEONARDO	 +	'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',' ',' ',' ' +#endif +}; + +const u16 STRING_IMANUFACTURER[12] = { +	(3<<8) | (2+2*11), +	'A','r','d','u','i','n','o',' ','L','L','C' +}; + +#ifdef CDC_ENABLED +#define DEVICE_CLASS 0x02 +#else +#define DEVICE_CLASS 0x00 +#endif + +//	DEVICE DESCRIPTOR +const DeviceDescriptor USB_DeviceDescriptor = +	D_DEVICE(0x00,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1); + +const DeviceDescriptor USB_DeviceDescriptorA = +	D_DEVICE(DEVICE_CLASS,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1); + +//================================================================== +//================================================================== + +volatile u8 _usbConfiguration = 0; + +static inline void WaitIN(void) +{ +	while (!(UEINTX & (1<<TXINI))); +} + +static inline void ClearIN(void) +{ +	UEINTX = ~(1<<TXINI); +} + +static inline void WaitOUT(void) +{ +	while (!(UEINTX & (1<<RXOUTI))) +		; +} + +static inline u8 WaitForINOrOUT() +{ +	while (!(UEINTX & ((1<<TXINI)|(1<<RXOUTI)))) +		; +	return (UEINTX & (1<<RXOUTI)) == 0; +} + +static inline void ClearOUT(void) +{ +	UEINTX = ~(1<<RXOUTI); +} + +void Recv(volatile u8* data, u8 count) +{ +	while (count--) +		*data++ = UEDATX; +	 +	RXLED1;					// light the RX LED +	RxLEDPulse = TX_RX_LED_PULSE_MS;	 +} + +static inline u8 Recv8() +{ +	RXLED1;					// light the RX LED +	RxLEDPulse = TX_RX_LED_PULSE_MS; + +	return UEDATX;	 +} + +static inline void Send8(u8 d) +{ +	UEDATX = d; +} + +static inline void SetEP(u8 ep) +{ +	UENUM = ep; +} + +static inline u8 FifoByteCount() +{ +	return UEBCLX; +} + +static inline u8 ReceivedSetupInt() +{ +	return UEINTX & (1<<RXSTPI); +} + +static inline void ClearSetupInt() +{ +	UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI)); +} + +static inline void Stall() +{ +	UECONX = (1<<STALLRQ) | (1<<EPEN); +} + +static inline u8 ReadWriteAllowed() +{ +	return UEINTX & (1<<RWAL); +} + +static inline u8 Stalled() +{ +	return UEINTX & (1<<STALLEDI); +} + +static inline u8 FifoFree() +{ +	return UEINTX & (1<<FIFOCON); +} + +static inline void ReleaseRX() +{ +	UEINTX = 0x6B;	// FIFOCON=0 NAKINI=1 RWAL=1 NAKOUTI=0 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=1 +} + +static inline void ReleaseTX() +{ +	UEINTX = 0x3A;	// FIFOCON=0 NAKINI=0 RWAL=1 NAKOUTI=1 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=0 +} + +static inline u8 FrameNumber() +{ +	return UDFNUML; +} + +//================================================================== +//================================================================== + +u8 USBGetConfiguration(void) +{ +	return _usbConfiguration; +} + +#define USB_RECV_TIMEOUT +class LockEP +{ +	u8 _sreg; +public: +	LockEP(u8 ep) : _sreg(SREG) +	{ +		cli(); +		SetEP(ep & 7); +	} +	~LockEP() +	{ +		SREG = _sreg; +	} +}; + +//	Number of bytes, assumes a rx endpoint +u8 USB_Available(u8 ep) +{ +	LockEP lock(ep); +	return FifoByteCount(); +} + +//	Non Blocking receive +//	Return number of bytes read +int USB_Recv(u8 ep, void* d, int len) +{ +	if (!_usbConfiguration || len < 0) +		return -1; +	 +	LockEP lock(ep); +	u8 n = FifoByteCount(); +	len = min(n,len); +	n = len; +	u8* dst = (u8*)d; +	while (n--) +		*dst++ = Recv8(); +	if (len && !FifoByteCount())	// release empty buffer +		ReleaseRX(); +	 +	return len; +} + +//	Recv 1 byte if ready +int USB_Recv(u8 ep) +{ +	u8 c; +	if (USB_Recv(ep,&c,1) != 1) +		return -1; +	return c; +} + +//	Space in send EP +u8 USB_SendSpace(u8 ep) +{ +	LockEP lock(ep); +	if (!ReadWriteAllowed()) +		return 0; +	return 64 - FifoByteCount(); +} + +//	Blocking Send of data to an endpoint +int USB_Send(u8 ep, const void* d, int len) +{ +	if (!_usbConfiguration) +		return -1; + +	int r = len; +	const u8* data = (const u8*)d; +	u8 zero = ep & TRANSFER_ZERO; +	u8 timeout = 250;		// 250ms timeout on send? TODO +	while (len) +	{ +		u8 n = USB_SendSpace(ep); +		if (n == 0) +		{ +			if (!(--timeout)) +				return -1; +			delay(1); +			continue; +		} + +		if (n > len) +			n = len; +		len -= n; +		{ +			LockEP lock(ep); +			if (ep & TRANSFER_ZERO) +			{ +				while (n--) +					Send8(0); +			} +			else if (ep & TRANSFER_PGM) +			{ +				while (n--) +					Send8(pgm_read_byte(data++)); +			} +			else +			{ +				while (n--) +					Send8(*data++); +			} +			if (!ReadWriteAllowed() || ((len == 0) && (ep & TRANSFER_RELEASE)))	// Release full buffer +				ReleaseTX(); +		} +	} +	TXLED1;					// light the TX LED +	TxLEDPulse = TX_RX_LED_PULSE_MS; +	return r; +} + +extern const u8 _initEndpoints[] PROGMEM; +const u8 _initEndpoints[] =  +{ +	0, +	 +#ifdef CDC_ENABLED +	EP_TYPE_INTERRUPT_IN,		// CDC_ENDPOINT_ACM +	EP_TYPE_BULK_OUT,			// CDC_ENDPOINT_OUT +	EP_TYPE_BULK_IN,			// CDC_ENDPOINT_IN +#endif + +#ifdef HID_ENABLED +	EP_TYPE_INTERRUPT_IN		// HID_ENDPOINT_INT +#endif +}; + +#define EP_SINGLE_64 0x32	// EP0 +#define EP_DOUBLE_64 0x36	// Other endpoints + +static +void InitEP(u8 index, u8 type, u8 size) +{ +	UENUM = index; +	UECONX = 1; +	UECFG0X = type; +	UECFG1X = size; +} + +static +void InitEndpoints() +{ +	for (u8 i = 1; i < sizeof(_initEndpoints); i++) +	{ +		UENUM = i; +		UECONX = 1; +		UECFG0X = pgm_read_byte(_initEndpoints+i); +		UECFG1X = EP_DOUBLE_64; +	} +	UERST = 0x7E;	// And reset them +	UERST = 0; +} + +//	Handle CLASS_INTERFACE requests +static +bool ClassInterfaceRequest(Setup& setup) +{ +	u8 i = setup.wIndex; + +#ifdef CDC_ENABLED +	if (CDC_ACM_INTERFACE == i) +		return CDC_Setup(setup); +#endif + +#ifdef HID_ENABLED +	if (HID_INTERFACE == i) +		return HID_Setup(setup); +#endif +	return false; +} + +int _cmark; +int _cend; +void InitControl(int end) +{ +	SetEP(0); +	_cmark = 0; +	_cend = end; +} + +static +bool SendControl(u8 d) +{ +	if (_cmark < _cend) +	{ +		if (!WaitForINOrOUT()) +			return false; +		Send8(d); +		if (!((_cmark + 1) & 0x3F)) +			ClearIN();	// Fifo is full, release this packet +	} +	_cmark++; +	return true; +}; + +//	Clipped by _cmark/_cend +int USB_SendControl(u8 flags, const void* d, int len) +{ +	int sent = len; +	const u8* data = (const u8*)d; +	bool pgm = flags & TRANSFER_PGM; +	while (len--) +	{ +		u8 c = pgm ? pgm_read_byte(data++) : *data++; +		if (!SendControl(c)) +			return -1; +	} +	return sent; +} + +//	Does not timeout or cross fifo boundaries +//	Will only work for transfers <= 64 bytes +//	TODO +int USB_RecvControl(void* d, int len) +{ +	WaitOUT(); +	Recv((u8*)d,len); +	ClearOUT(); +	return len; +} + +int SendInterfaces() +{ +	int total = 0; +	u8 interfaces = 0; + +#ifdef CDC_ENABLED +	total = CDC_GetInterface(&interfaces); +#endif + +#ifdef HID_ENABLED +	total += HID_GetInterface(&interfaces); +#endif + +	return interfaces; +} + +//	Construct a dynamic configuration descriptor +//	This really needs dynamic endpoint allocation etc +//	TODO +static +bool SendConfiguration(int maxlen) +{ +	//	Count and measure interfaces +	InitControl(0);	 +	int interfaces = SendInterfaces(); +	ConfigDescriptor config = D_CONFIG(_cmark + sizeof(ConfigDescriptor),interfaces); + +	//	Now send them +	InitControl(maxlen); +	USB_SendControl(0,&config,sizeof(ConfigDescriptor)); +	SendInterfaces(); +	return true; +} + +u8 _cdcComposite = 0; + +static +bool SendDescriptor(Setup& setup) +{ +	u8 t = setup.wValueH; +	if (USB_CONFIGURATION_DESCRIPTOR_TYPE == t) +		return SendConfiguration(setup.wLength); + +	InitControl(setup.wLength); +#ifdef HID_ENABLED +	if (HID_REPORT_DESCRIPTOR_TYPE == t) +		return HID_GetDescriptor(t); +#endif + +	u8 desc_length = 0; +	const u8* desc_addr = 0; +	if (USB_DEVICE_DESCRIPTOR_TYPE == t) +	{ +		if (setup.wLength == 8) +			_cdcComposite = 1; +		desc_addr = _cdcComposite ?  (const u8*)&USB_DeviceDescriptorA : (const u8*)&USB_DeviceDescriptor; +	} +	else if (USB_STRING_DESCRIPTOR_TYPE == t) +	{ +		if (setup.wValueL == 0) +			desc_addr = (const u8*)&STRING_LANGUAGE; +		else if (setup.wValueL == IPRODUCT)  +			desc_addr = (const u8*)&STRING_IPRODUCT; +		else if (setup.wValueL == IMANUFACTURER) +			desc_addr = (const u8*)&STRING_IMANUFACTURER; +		else +			return false; +	} + +	if (desc_addr == 0) +		return false; +	if (desc_length == 0) +		desc_length = pgm_read_byte(desc_addr); + +	USB_SendControl(TRANSFER_PGM,desc_addr,desc_length); +	return true; +} + +//	Endpoint 0 interrupt +ISR(USB_COM_vect) +{ +    SetEP(0); +	if (!ReceivedSetupInt()) +		return; + +	Setup setup; +	Recv((u8*)&setup,8); +	ClearSetupInt(); + +	u8 requestType = setup.bmRequestType; +	if (requestType & REQUEST_DEVICETOHOST) +		WaitIN(); +	else +		ClearIN(); + +    bool ok = true; +	if (REQUEST_STANDARD == (requestType & REQUEST_TYPE)) +	{ +		//	Standard Requests +		u8 r = setup.bRequest; +		if (GET_STATUS == r) +		{ +			Send8(0);		// TODO +			Send8(0); +		} +		else if (CLEAR_FEATURE == r) +		{ +		} +		else if (SET_FEATURE == r) +		{ +		} +		else if (SET_ADDRESS == r) +		{ +			WaitIN(); +			UDADDR = setup.wValueL | (1<<ADDEN); +		} +		else if (GET_DESCRIPTOR == r) +		{ +			ok = SendDescriptor(setup); +		} +		else if (SET_DESCRIPTOR == r) +		{ +			ok = false; +		} +		else if (GET_CONFIGURATION == r) +		{ +			Send8(1); +		} +		else if (SET_CONFIGURATION == r) +		{ +			if (REQUEST_DEVICE == (requestType & REQUEST_RECIPIENT)) +			{ +				InitEndpoints(); +				_usbConfiguration = setup.wValueL; +			} else +				ok = false; +		} +		else if (GET_INTERFACE == r) +		{ +		} +		else if (SET_INTERFACE == r) +		{ +		} +	} +	else +	{ +		InitControl(setup.wLength);		//	Max length of transfer +		ok = ClassInterfaceRequest(setup); +	} + +	if (ok) +		ClearIN(); +	else +	{ +		Stall(); +	} +} + +void USB_Flush(u8 ep) +{ +	SetEP(ep); +	if (FifoByteCount()) +		ReleaseTX(); +} + +//	General interrupt +ISR(USB_GEN_vect) +{ +	u8 udint = UDINT; +	UDINT = 0; + +	//	End of Reset +	if (udint & (1<<EORSTI)) +	{ +		InitEP(0,EP_TYPE_CONTROL,EP_SINGLE_64);	// init ep0 +		_usbConfiguration = 0;			// not configured yet +		UEIENX = 1 << RXSTPE;			// Enable interrupts for ep0 +	} + +	//	Start of Frame - happens every millisecond so we use it for TX and RX LED one-shot timing, too +	if (udint & (1<<SOFI)) +	{ +#ifdef CDC_ENABLED +		USB_Flush(CDC_TX);				// Send a tx frame if found +#endif +		 +		// check whether the one-shot period has elapsed.  if so, turn off the LED +		if (TxLEDPulse && !(--TxLEDPulse)) +			TXLED0; +		if (RxLEDPulse && !(--RxLEDPulse)) +			RXLED0; +	} +} + +//	VBUS or counting frames +//	Any frame counting? +u8 USBConnected() +{ +	u8 f = UDFNUML; +	delay(3); +	return f != UDFNUML; +} + +//======================================================================= +//======================================================================= + +USB_ USB; + +USB_::USB_() +{ +} + +void USB_::attach() +{ +	_usbConfiguration = 0; +	UHWCON = 0x01;						// power internal reg +	USBCON = (1<<USBE)|(1<<FRZCLK);		// clock frozen, usb enabled +	PLLCSR = 0x12;						// Need 16 MHz xtal +	while (!(PLLCSR & (1<<PLOCK)))		// wait for lock pll +		; +	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 +	 +	TX_RX_LED_INIT; +} + +void USB_::detach() +{ +} + +//	Check for interrupts +//	TODO: VBUS detection +bool USB_::configured() +{ +	return _usbConfiguration; +} + +void USB_::poll() +{ +} + +#endif /* if defined(USBCON) */
\ No newline at end of file diff --git a/cores/arduino/USBCore.h b/cores/arduino/USBCore.h new file mode 100644 index 0000000..8d13806 --- /dev/null +++ b/cores/arduino/USBCore.h @@ -0,0 +1,303 @@ + +// Copyright (c) 2010, 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.   +*/ + +#ifndef __USBCORE_H__ +#define __USBCORE_H__ + +//	Standard requests +#define GET_STATUS			0 +#define CLEAR_FEATURE		1 +#define SET_FEATURE			3 +#define SET_ADDRESS			5 +#define GET_DESCRIPTOR		6 +#define SET_DESCRIPTOR		7 +#define GET_CONFIGURATION	8 +#define SET_CONFIGURATION	9 +#define GET_INTERFACE		10 +#define SET_INTERFACE		11 + + +// bmRequestType +#define REQUEST_HOSTTODEVICE	0x00 +#define REQUEST_DEVICETOHOST	0x80 +#define REQUEST_DIRECTION		0x80 + +#define REQUEST_STANDARD		0x00 +#define REQUEST_CLASS			0x20 +#define REQUEST_VENDOR			0x40 +#define REQUEST_TYPE			0x60 + +#define REQUEST_DEVICE			0x00 +#define REQUEST_INTERFACE		0x01 +#define REQUEST_ENDPOINT		0x02 +#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) + +//	Class requests + +#define CDC_SET_LINE_CODING			0x20 +#define CDC_GET_LINE_CODING			0x21 +#define CDC_SET_CONTROL_LINE_STATE	0x22 + +#define MSC_RESET					0xFF +#define MSC_GET_MAX_LUN				0xFE + +#define HID_GET_REPORT				0x01 +#define HID_GET_IDLE				0x02 +#define HID_GET_PROTOCOL			0x03 +#define HID_SET_REPORT				0x09 +#define HID_SET_IDLE				0x0A +#define HID_SET_PROTOCOL			0x0B + +//	Descriptors + +#define USB_DEVICE_DESC_SIZE 18 +#define USB_CONFIGUARTION_DESC_SIZE 9 +#define USB_INTERFACE_DESC_SIZE 9 +#define USB_ENDPOINT_DESC_SIZE 7 + +#define USB_DEVICE_DESCRIPTOR_TYPE             1 +#define USB_CONFIGURATION_DESCRIPTOR_TYPE      2 +#define USB_STRING_DESCRIPTOR_TYPE             3 +#define USB_INTERFACE_DESCRIPTOR_TYPE          4 +#define USB_ENDPOINT_DESCRIPTOR_TYPE           5 + +#define USB_DEVICE_CLASS_COMMUNICATIONS        0x02 +#define USB_DEVICE_CLASS_HUMAN_INTERFACE       0x03 +#define USB_DEVICE_CLASS_STORAGE               0x08 +#define USB_DEVICE_CLASS_VENDOR_SPECIFIC       0xFF + +#define USB_CONFIG_POWERED_MASK                0x40 +#define USB_CONFIG_BUS_POWERED                 0x80 +#define USB_CONFIG_SELF_POWERED                0xC0 +#define USB_CONFIG_REMOTE_WAKEUP               0x20 + +// bMaxPower in Configuration Descriptor +#define USB_CONFIG_POWER_MA(mA)                ((mA)/2) + +// 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_TYPE_MASK                 0x03 +#define USB_ENDPOINT_TYPE_CONTROL              0x00 +#define USB_ENDPOINT_TYPE_ISOCHRONOUS          0x01 +#define USB_ENDPOINT_TYPE_BULK                 0x02 +#define USB_ENDPOINT_TYPE_INTERRUPT            0x03 + +#define TOBYTES(x) ((x) & 0xFF),(((x) >> 8) & 0xFF) + +#define CDC_V1_10                               0x0110 +#define CDC_COMMUNICATION_INTERFACE_CLASS       0x02 + +#define CDC_CALL_MANAGEMENT                     0x01 +#define CDC_ABSTRACT_CONTROL_MODEL              0x02 +#define CDC_HEADER                              0x00 +#define CDC_ABSTRACT_CONTROL_MANAGEMENT         0x02 +#define CDC_UNION                               0x06 +#define CDC_CS_INTERFACE                        0x24 +#define CDC_CS_ENDPOINT                         0x25 +#define CDC_DATA_INTERFACE_CLASS                0x0A + +#define MSC_SUBCLASS_SCSI						0x06  +#define MSC_PROTOCOL_BULK_ONLY					0x50  + +#define HID_HID_DESCRIPTOR_TYPE					0x21 +#define HID_REPORT_DESCRIPTOR_TYPE				0x22 +#define HID_PHYSICAL_DESCRIPTOR_TYPE			0x23 + + +//	Device +typedef struct { +	u8 len;				// 18 +	u8 dtype;			// 1 USB_DEVICE_DESCRIPTOR_TYPE +	u16 usbVersion;		// 0x200 +	u8	deviceClass; +	u8	deviceSubClass; +	u8	deviceProtocol; +	u8	packetSize0;	// Packet 0 +	u16	idVendor; +	u16	idProduct; +	u16	deviceVersion;	// 0x100 +	u8	iManufacturer; +	u8	iProduct; +	u8	iSerialNumber; +	u8	bNumConfigurations; +} DeviceDescriptor; + +//	Config +typedef struct { +	u8	len;			// 9 +	u8	dtype;			// 2 +	u16 clen;			// total length +	u8	numInterfaces; +	u8	config; +	u8	iconfig; +	u8	attributes; +	u8	maxPower; +} ConfigDescriptor; + +//	String + +//	Interface +typedef struct +{ +	u8 len;		// 9 +	u8 dtype;	// 4 +	u8 number; +	u8 alternate; +	u8 numEndpoints; +	u8 interfaceClass; +	u8 interfaceSubClass; +	u8 protocol; +	u8 iInterface; +} InterfaceDescriptor; + +//	Endpoint +typedef struct +{ +	u8 len;		// 7 +	u8 dtype;	// 5 +	u8 addr; +	u8 attr; +	u16 packetSize; +	u8 interval; +} EndpointDescriptor; + +// Interface Association Descriptor +// Used to bind 2 interfaces together in CDC compostite device +typedef struct +{ +	u8 len;				// 8 +	u8 dtype;			// 11 +	u8 firstInterface; +	u8 interfaceCount; +	u8 functionClass; +	u8 funtionSubClass; +	u8 functionProtocol; +	u8 iInterface; +} IADDescriptor; + +//	CDC CS interface descriptor +typedef struct +{ +	u8 len;		// 5 +	u8 dtype;	// 0x24 +	u8 subtype; +	u8 d0; +	u8 d1; +} CDCCSInterfaceDescriptor; + +typedef struct +{ +	u8 len;		// 4 +	u8 dtype;	// 0x24 +	u8 subtype; +	u8 d0; +} CDCCSInterfaceDescriptor4; + +typedef struct  +{ +    u8	len; +    u8 	dtype;		// 0x24 +    u8 	subtype;	// 1 +    u8 	bmCapabilities; +    u8 	bDataInterface; +} CMFunctionalDescriptor; +	 +typedef struct  +{ +    u8	len; +    u8 	dtype;		// 0x24 +    u8 	subtype;	// 1 +    u8 	bmCapabilities; +} ACMFunctionalDescriptor; + +typedef struct  +{ +	//	IAD +	IADDescriptor				iad;	// Only needed on compound device + +	//	Control +	InterfaceDescriptor			cif;	//  +	CDCCSInterfaceDescriptor	header; +	CMFunctionalDescriptor		callManagement;			// Call Management +	ACMFunctionalDescriptor		controlManagement;		// ACM +	CDCCSInterfaceDescriptor	functionalDescriptor;	// CDC_UNION +	EndpointDescriptor			cifin; + +	//	Data +	InterfaceDescriptor			dif; +	EndpointDescriptor			in; +	EndpointDescriptor			out; +} CDCDescriptor; + +typedef struct  +{ +	InterfaceDescriptor			msc; +	EndpointDescriptor			in; +	EndpointDescriptor			out; +} MSCDescriptor; + +typedef struct +{ +	u8 len;			// 9 +	u8 dtype;		// 0x21 +	u8 addr; +	u8	versionL;	// 0x101 +	u8	versionH;	// 0x101 +	u8	country; +	u8	desctype;	// 0x22 report +	u8	descLenL; +	u8	descLenH; +} HIDDescDescriptor; + +typedef struct  +{ +	InterfaceDescriptor			hid; +	HIDDescDescriptor			desc; +	EndpointDescriptor			in; +} HIDDescriptor; + + +#define D_DEVICE(_class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs) \ +	{ 18, 1, 0x200, _class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs } + +#define D_CONFIG(_totalLength,_interfaces) \ +	{ 9, 2, _totalLength,_interfaces, 1, 0, USB_CONFIG_BUS_POWERED, USB_CONFIG_POWER_MA(500) } + +#define D_INTERFACE(_n,_numEndpoints,_class,_subClass,_protocol) \ +	{ 9, 4, _n, 0, _numEndpoints, _class,_subClass, _protocol, 0 } + +#define D_ENDPOINT(_addr,_attr,_packetSize, _interval) \ +	{ 7, 5, _addr,_attr,_packetSize, _interval } + +#define D_IAD(_firstInterface, _count, _class, _subClass, _protocol) \ +	{ 8, 11, _firstInterface, _count, _class, _subClass, _protocol, 0 } + +#define D_HIDREPORT(_descriptorLength) \ +	{ 9, 0x21, 0x1, 0x1, 0, 1, 0x22, _descriptorLength, 0 } + +#define D_CDCCS(_subtype,_d0,_d1)	{ 5, 0x24, _subtype, _d0, _d1 } +#define D_CDCCS4(_subtype,_d0)		{ 4, 0x24, _subtype, _d0 } + + +#endif
\ No newline at end of file diff --git a/cores/arduino/USBDesc.h b/cores/arduino/USBDesc.h new file mode 100644 index 0000000..549ed9e --- /dev/null +++ b/cores/arduino/USBDesc.h @@ -0,0 +1,67 @@ + + +/* 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.   +*/ + +#define CDC_ENABLED +#define HID_ENABLED + + +#ifdef CDC_ENABLED +#define CDC_INTERFACE_COUNT	2 +#define CDC_ENPOINT_COUNT	3 +#else +#define CDC_INTERFACE_COUNT	0 +#define CDC_ENPOINT_COUNT	0 +#endif + +#ifdef HID_ENABLED +#define HID_INTERFACE_COUNT	1 +#define HID_ENPOINT_COUNT	1 +#else +#define HID_INTERFACE_COUNT	0 +#define HID_ENPOINT_COUNT	0 +#endif + +#define CDC_ACM_INTERFACE	0	// CDC ACM +#define CDC_DATA_INTERFACE	1	// CDC Data +#define CDC_FIRST_ENDPOINT	1 +#define CDC_ENDPOINT_ACM	(CDC_FIRST_ENDPOINT)							// CDC First +#define CDC_ENDPOINT_OUT	(CDC_FIRST_ENDPOINT+1) +#define CDC_ENDPOINT_IN		(CDC_FIRST_ENDPOINT+2) + +#define HID_INTERFACE		(CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT)		// HID Interface +#define HID_FIRST_ENDPOINT	(CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT) +#define HID_ENDPOINT_INT	(HID_FIRST_ENDPOINT) + +#define INTERFACE_COUNT		(MSC_INTERFACE + MSC_INTERFACE_COUNT) + +#ifdef CDC_ENABLED +#define CDC_RX CDC_ENDPOINT_OUT +#define CDC_TX CDC_ENDPOINT_IN +#endif + +#ifdef HID_ENABLED +#define HID_TX HID_ENDPOINT_INT +#endif + +#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/WString.cpp b/cores/arduino/WString.cpp index f90cef0..ad8d828 100644 --- a/cores/arduino/WString.cpp +++ b/cores/arduino/WString.cpp @@ -498,7 +498,7 @@ int String::lastIndexOf( char theChar ) const  	return lastIndexOf(theChar, len - 1);  } -int String::lastIndexOf(char ch, int fromIndex) const +int String::lastIndexOf(char ch, unsigned int fromIndex) const  {  	if (fromIndex >= len || fromIndex < 0) return -1;  	char tempchar = buffer[fromIndex + 1]; @@ -514,7 +514,7 @@ int String::lastIndexOf(const String &s2) const  	return lastIndexOf(s2, len - s2.len);  } -int String::lastIndexOf(const String &s2, int fromIndex) 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 (fromIndex >= len) fromIndex = len - 1; @@ -522,7 +522,7 @@ int String::lastIndexOf(const String &s2, int fromIndex) const  	for (char *p = buffer; p <= buffer + fromIndex; p++) {  		p = strstr(p, s2.buffer);  		if (!p) break; -		if (p - buffer <= fromIndex) found = p - buffer; +		if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer;  	}  	return found;  } diff --git a/cores/arduino/WString.h b/cores/arduino/WString.h index a601aca..d76d2a3 100644 --- a/cores/arduino/WString.h +++ b/cores/arduino/WString.h @@ -154,9 +154,9 @@ public:  	int indexOf( const String &str ) const;  	int indexOf( const String &str, unsigned int fromIndex ) const;  	int lastIndexOf( char ch ) const; -	int lastIndexOf( char ch, int fromIndex ) const; +	int lastIndexOf( char ch, unsigned int fromIndex ) const;  	int lastIndexOf( const String &str ) const; -	int lastIndexOf( const String &str, int fromIndex ) const; +	int lastIndexOf( const String &str, unsigned int fromIndex ) const;  	String substring( unsigned int beginIndex ) const;  	String substring( unsigned int beginIndex, unsigned int endIndex ) const; diff --git a/cores/arduino/main.cpp b/cores/arduino/main.cpp index 632a4d9..0ef5256 100755 --- a/cores/arduino/main.cpp +++ b/cores/arduino/main.cpp @@ -5,6 +5,10 @@ int main(void)  {  	init(); +#if defined(USBCON) +	USB.attach(); +#endif +	  	setup();  	for (;;) { diff --git a/cores/arduino/wiring.c b/cores/arduino/wiring.c index ce4cad6..1b3fd44 100755 --- a/cores/arduino/wiring.c +++ b/cores/arduino/wiring.c @@ -41,7 +41,11 @@ volatile unsigned long timer0_overflow_count = 0;  volatile unsigned long timer0_millis = 0;  static unsigned char timer0_fract = 0; +#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) +SIGNAL(TIM0_OVF_vect) +#else  SIGNAL(TIMER0_OVF_vect) +#endif  {  	// copy these to local variables so they can be stored in registers  	// (volatile variables must be read from memory on every access) diff --git a/cores/arduino/wiring_analog.c b/cores/arduino/wiring_analog.c index d248f4c..2b1f3a0 100644 --- a/cores/arduino/wiring_analog.c +++ b/cores/arduino/wiring_analog.c @@ -46,8 +46,11 @@ int analogRead(uint8_t pin)  #else  	if (pin >= 14) pin -= 14; // allow for channel or pin numbers  #endif - -#if defined(ADCSRB) && defined(MUX5) +	 +#if defined(__AVR_ATmega32U4__) +	pin = analogPinToChannel(pin); +	ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5); +#elif defined(ADCSRB) && defined(MUX5)  	// the MUX5 bit of ADCSRB selects whether we're reading from channels  	// 0 to 7 (MUX5 low) or 8 to 15 (MUX5 high).  	ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5); @@ -222,6 +225,14 @@ void analogWrite(uint8_t pin, int val)  				OCR4C = val; // set pwm duty  				break;  			#endif +				 +			#if defined(TCCR4A) && defined(COM4D1) +			case TIMER4D: +				// connect pwm to pin on timer 4, channel D +				sbi(TCCR4A, COM4D1); +				OCR4D = val; // set pwm duty +				break; +			#endif  			#if defined(TCCR5A) && defined(COM5A1)  			case TIMER5A: diff --git a/cores/arduino/wiring_private.h b/cores/arduino/wiring_private.h index 74c0d06..41d1d40 100755 --- a/cores/arduino/wiring_private.h +++ b/cores/arduino/wiring_private.h @@ -27,7 +27,6 @@  #include <avr/io.h>  #include <avr/interrupt.h> -#include <avr/delay.h>  #include <stdio.h>  #include <stdarg.h> | 
