aboutsummaryrefslogtreecommitdiff
path: root/cores/arduino
diff options
context:
space:
mode:
Diffstat (limited to 'cores/arduino')
-rw-r--r--cores/arduino/CDC.cpp91
-rw-r--r--cores/arduino/HID.cpp3
-rw-r--r--cores/arduino/USBAPI.h6
-rw-r--r--cores/arduino/USBCore.cpp2
-rw-r--r--cores/arduino/USBDesc.h2
-rw-r--r--[-rwxr-xr-x]cores/arduino/WInterrupts.c38
-rw-r--r--[-rwxr-xr-x]cores/arduino/wiring.c15
-rw-r--r--cores/arduino/wiring_analog.c18
-rw-r--r--[-rwxr-xr-x]cores/arduino/wiring_digital.c8
9 files changed, 141 insertions, 42 deletions
diff --git a/cores/arduino/CDC.cpp b/cores/arduino/CDC.cpp
index 14a0eae..6d3929e 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
+
+ // We check DTR state to determine if host port is open (bit 0 of lineState).
+ // Serial1.print(">"); Serial1.println(_usbLineInfo.lineState, HEX);
+ if ((_usbLineInfo.lineState & 0x01) == 0 && _usbLineInfo.dwDTERate == 1200) {
+ *(uint16_t *)0x0A00 = 0x7777;
+ wdt_enable(WDTO_250MS);
+ } 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 *)0x0A00 = 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)
@@ -172,4 +215,4 @@ size_t Serial_::write(uint8_t c)
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..e6fb5f7 100644
--- a/cores/arduino/HID.cpp
+++ b/cores/arduino/HID.cpp
@@ -406,7 +406,8 @@ const uint8_t _asciimap[128] =
};
uint8_t USBPutChar(uint8_t c);
-size_t Keyboard_::write(uint8_t c)
+
+size_t Keyboard_::type(uint8_t c)
{
// Keydown
{
diff --git a/cores/arduino/USBAPI.h b/cores/arduino/USBAPI.h
index 26a2032..6a0b989 100644
--- a/cores/arduino/USBAPI.h
+++ b/cores/arduino/USBAPI.h
@@ -27,11 +27,14 @@ 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);
@@ -101,7 +104,8 @@ private:
void setKeyMap(KeyMap* keyMap);
public:
Keyboard_();
- virtual size_t write(uint8_t);
+ virtual size_t write(uint8_t c) {type(c);};
+ virtual size_t type(uint8_t c);
};
extern Keyboard_ Keyboard;
diff --git a/cores/arduino/USBCore.cpp b/cores/arduino/USBCore.cpp
index 398bc73..7924078 100644
--- a/cores/arduino/USBCore.cpp
+++ b/cores/arduino/USBCore.cpp
@@ -599,6 +599,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
diff --git a/cores/arduino/USBDesc.h b/cores/arduino/USBDesc.h
index 549ed9e..5cd90ad 100644
--- a/cores/arduino/USBDesc.h
+++ b/cores/arduino/USBDesc.h
@@ -60,7 +60,7 @@
#define IMANUFACTURER 1
#define IPRODUCT 2
-#define USB_PID_LEONARDO 0x0034
+#define USB_PID_LEONARDO 0x0801
#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 4f035eb..3c852ed 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);
@@ -136,7 +148,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;
@@ -198,7 +217,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/wiring.c b/cores/arduino/wiring.c
index e7f7cde..fb447eb 100755..100644
--- a/cores/arduino/wiring.c
+++ b/cores/arduino/wiring.c
@@ -278,12 +278,25 @@ 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(TCCR4A, COM4A1); // clear channel A on output compare match
+ cbi(TCCR4A, COM4A0);
+ sbi(TCCR4C, COM4D1); // clear channel D on output compare match
+ cbi(TCCR4C, COM4D0);
+ 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..8a6fef3 100644
--- a/cores/arduino/wiring_analog.c
+++ b/cores/arduino/wiring_analog.c
@@ -204,14 +204,14 @@ 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
+ 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 +228,15 @@ void analogWrite(uint8_t pin, int val)
break;
#endif
- #if defined(TCCR4A) && defined(COM4D1)
- case TIMER4D:
+ #if defined(TCCR4C)
+ case TIMER4D:
// connect pwm to pin on timer 4, channel D
- sbi(TCCR4A, COM4D1);
- OCR4D = val; // set pwm duty
+ sbi(TCCR4C, COM4D1);
+ 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 +271,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;