diff options
Diffstat (limited to 'cores/arduino')
-rw-r--r-- | cores/arduino/CDC.cpp | 91 | ||||
-rw-r--r-- | cores/arduino/HID.cpp | 3 | ||||
-rw-r--r-- | cores/arduino/USBAPI.h | 6 | ||||
-rw-r--r-- | cores/arduino/USBCore.cpp | 2 | ||||
-rw-r--r-- | cores/arduino/USBDesc.h | 2 | ||||
-rw-r--r--[-rwxr-xr-x] | cores/arduino/WInterrupts.c | 38 | ||||
-rw-r--r--[-rwxr-xr-x] | cores/arduino/wiring.c | 15 | ||||
-rw-r--r-- | cores/arduino/wiring_analog.c | 18 | ||||
-rw-r--r--[-rwxr-xr-x] | cores/arduino/wiring_digital.c | 8 |
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; |