aboutsummaryrefslogtreecommitdiff
path: root/cores
diff options
context:
space:
mode:
Diffstat (limited to 'cores')
-rw-r--r--cores/arduino/CDC.cpp106
-rw-r--r--cores/arduino/HID.cpp144
-rw-r--r--cores/arduino/HardwareSerial.cpp4
-rw-r--r--cores/arduino/HardwareSerial.h1
-rw-r--r--cores/arduino/USBAPI.h81
-rw-r--r--cores/arduino/USBCore.cpp32
-rw-r--r--cores/arduino/USBDesc.h4
-rw-r--r--[-rwxr-xr-x]cores/arduino/WInterrupts.c38
-rw-r--r--[-rwxr-xr-x]cores/arduino/main.cpp2
-rw-r--r--[-rwxr-xr-x]cores/arduino/wiring.c11
-rw-r--r--cores/arduino/wiring_analog.c24
-rw-r--r--[-rwxr-xr-x]cores/arduino/wiring_digital.c8
12 files changed, 340 insertions, 115 deletions
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 9985b78..f40ddee 100644
--- a/cores/arduino/HardwareSerial.cpp
+++ b/cores/arduino/HardwareSerial.cpp
@@ -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/USBAPI.h b/cores/arduino/USBAPI.h
index 26a2032..d5abdb6 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,19 @@ 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);
+ operator bool();
};
extern Serial_ Serial;
@@ -54,12 +58,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 +73,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 +118,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 398bc73..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
@@ -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 3b9fe08..8f3ec84 100755..100644
--- a/cores/arduino/WInterrupts.c
+++ b/cores/arduino/WInterrupts.c
@@ -47,7 +47,19 @@ 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;
+#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
case 2:
EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
EIMSK |= (1 << INT0);
@@ -80,7 +92,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);
@@ -134,7 +146,14 @@ 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;
+#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
case 2:
EIMSK &= ~(1 << INT0);
break;
@@ -196,7 +215,18 @@ 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]();
+}
+
+#elif defined(EICRA) && defined(EICRB)
SIGNAL(INT0_vect) {
if(intFunc[EXTERNAL_INT_2])
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 a8bc817..0e9881f 100644
--- a/cores/arduino/wiring_analog.c
+++ b/cores/arduino/wiring_analog.c
@@ -206,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
@@ -230,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
@@ -272,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 584a28a..be323b1 100755..100644
--- a/cores/arduino/wiring_digital.c
+++ b/cores/arduino/wiring_digital.c
@@ -115,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;