From 7aed6f3dec79dc0346a8875a4eef40f2292917d0 Mon Sep 17 00:00:00 2001 From: Mark Sproul <msproul@mark-sprouls-macbook-pro-2.local> Date: Thu, 30 Sep 2010 22:11:46 -0400 Subject: [PATCH 1/6] Using register #ifdefs instead of cpu #ifdefs --- .../arduino/cores/arduino/HardwareSerial.cpp | 197 ++++++++++++++---- .../arduino/cores/arduino/HardwareSerial.h | 22 +- 2 files changed, 170 insertions(+), 49 deletions(-) mode change 100755 => 100644 hardware/arduino/cores/arduino/HardwareSerial.cpp mode change 100755 => 100644 hardware/arduino/cores/arduino/HardwareSerial.h diff --git a/hardware/arduino/cores/arduino/HardwareSerial.cpp b/hardware/arduino/cores/arduino/HardwareSerial.cpp old mode 100755 new mode 100644 index e7ac21f7cf2..28449f69bdf --- a/hardware/arduino/cores/arduino/HardwareSerial.cpp +++ b/hardware/arduino/cores/arduino/HardwareSerial.cpp @@ -18,6 +18,17 @@ Modified 23 November 2006 by David A. Mellis */ +//******************************************************************************************* +//* Mar 14, 2010 <MLS> Mark Sproul fixed bug in __AVR_ATmega644__ interrupt vector +//* Mar 25, 2010 <MLS> Fixed bug in __AVR_ATmega644P__ interrupt vector +//* Apr 2, 2010 <MLS> Changed RX_BUFFER_SIZE to 32 for smaller ram processors +//* Jul 30, 2010 <MLS> Chainging #ifdefs to register and signals instead of CPU type +//* Aug 3, 2010 <MLS> Tested on 644P 645 1280, 2560 328 and others +//* Aug 16, 2010 <MLS> Added support for Atmega32 +//* Aug 31, 2010 <MLS> The ATmega32U4 has uart1 but NOT uart0 +//* Sep 5, 2010 <MLS> V0019 was released, migrated changes into 0019 +//* Sep 28, 2010 <MLS> V0020 was released, migrated changes into 0020 +//******************************************************************************************* #include <stdlib.h> #include <stdio.h> @@ -26,28 +37,46 @@ #include "wiring.h" #include "wiring_private.h" +//******************************************************************************************* +//* this next line disables the entire HardwareSerial.cpp, +//* this is so I can support Attiny series and any other chip without a uart +#if defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H) + #include "HardwareSerial.h" // Define constants and variables for buffering incoming serial data. We're // using a ring buffer (I think), in which rx_buffer_head is the index of the // location to which to write the next incoming character and rx_buffer_tail // is the index of the location from which to read. -#define RX_BUFFER_SIZE 128 +#if (RAMEND < 1500) + #define RX_BUFFER_SIZE 32 +#else + #define RX_BUFFER_SIZE 128 +#endif -struct ring_buffer { - unsigned char buffer[RX_BUFFER_SIZE]; - int head; - int tail; +struct ring_buffer +{ + unsigned char buffer[RX_BUFFER_SIZE]; + int head; + int tail; }; -ring_buffer rx_buffer = { { 0 }, 0, 0 }; +#if defined(UBRRH) || defined(UBRR0H) + ring_buffer rx_buffer = { { 0 }, 0, 0 }; +#endif -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) -ring_buffer rx_buffer1 = { { 0 }, 0, 0 }; -ring_buffer rx_buffer2 = { { 0 }, 0, 0 }; -ring_buffer rx_buffer3 = { { 0 }, 0, 0 }; +//#if defined(__AVR_ATmega1280__) +#if defined(UBRR1H) + ring_buffer rx_buffer1 = { { 0 }, 0, 0 }; +#endif +#if defined(UBRR2H) + ring_buffer rx_buffer2 = { { 0 }, 0, 0 }; +#endif +#if defined(UBRR3H) + ring_buffer rx_buffer3 = { { 0 }, 0, 0 }; #endif +//******************************************************************************************* inline void store_char(unsigned char c, ring_buffer *rx_buffer) { int i = (rx_buffer->head + 1) % RX_BUFFER_SIZE; @@ -62,52 +91,112 @@ inline void store_char(unsigned char c, ring_buffer *rx_buffer) } } -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) - -SIGNAL(SIG_USART0_RECV) +#if defined(USART_RX_vect) +//******************************************************************************************* +SIGNAL(USART_RX_vect) { - unsigned char c = UDR0; - store_char(c, &rx_buffer); +#if defined(UDR0) + unsigned char c = UDR0; +#elif defined(UDR) + unsigned char c = UDR; // atmega8535 +#else + #error UDR not defined +#endif + store_char(c, &rx_buffer); } - -SIGNAL(SIG_USART1_RECV) +#elif defined(SIG_USART0_RECV) && defined(UDR0) +//******************************************************************************************* +SIGNAL(SIG_USART0_RECV) { - unsigned char c = UDR1; - store_char(c, &rx_buffer1); + unsigned char c = UDR0; + store_char(c, &rx_buffer); } - -SIGNAL(SIG_USART2_RECV) +#elif defined(SIG_UART0_RECV) && defined(UDR0) +//******************************************************************************************* +SIGNAL(SIG_UART0_RECV) { - unsigned char c = UDR2; - store_char(c, &rx_buffer2); + unsigned char c = UDR0; + store_char(c, &rx_buffer); } - -SIGNAL(SIG_USART3_RECV) +//#elif defined(SIG_USART_RECV) +#elif defined(USART0_RX_vect) +//******************************************************************************************* +//* fixed by Mark Sproul March 25, 2010 +//* this is on the 644/644p +//SIGNAL(SIG_USART_RECV) +SIGNAL(USART0_RX_vect) { - unsigned char c = UDR3; - store_char(c, &rx_buffer3); -} - +#if defined(UDR0) + unsigned char c = UDR0; +#elif defined(UDR) + unsigned char c = UDR; // atmega8, atmega32 #else - -#if defined(__AVR_ATmega8__) + #error UDR not defined +#endif + store_char(c, &rx_buffer); +} +#elif defined(SIG_UART_RECV) +//******************************************************************************************* +//* this is for atmega8 SIGNAL(SIG_UART_RECV) +{ +#if defined(UDR0) + unsigned char c = UDR0; // atmega645 +#elif defined(UDR) + unsigned char c = UDR; // atmega8 +#endif + + store_char(c, &rx_buffer); +} +#elif defined(USBCON) + #warning No interrupt handler for usart 0 + #warning Serial(0) is on USB interface #else -SIGNAL(USART_RX_vect) + #error No interrupt handler for usart 0 #endif + +//#if defined(SIG_USART1_RECV) +#if defined(USART1_RX_vect) +//******************************************************************************************* +//SIGNAL(SIG_USART1_RECV) +SIGNAL(USART1_RX_vect) { -#if defined(__AVR_ATmega8__) - unsigned char c = UDR; -#else - unsigned char c = UDR0; + unsigned char c = UDR1; + store_char(c, &rx_buffer1); +} +#elif defined(SIG_USART1_RECV) + #error SIG_USART1_RECV #endif - store_char(c, &rx_buffer); + + +//#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#if defined(USART2_RX_vect) +//******************************************************************************************* +SIGNAL(USART2_RX_vect) +{ + unsigned char c = UDR2; + store_char(c, &rx_buffer2); } +#elif defined(SIG_USART2_RECV) + #error SIG_USART2_RECV +#endif +#if defined(USART3_RX_vect) +//******************************************************************************************* +SIGNAL(USART3_RX_vect) +{ + unsigned char c = UDR3; + store_char(c, &rx_buffer3); +} +#elif defined(SIG_USART3_RECV) + #error SIG_USART3_RECV #endif + + // Constructors //////////////////////////////////////////////////////////////// +//******************************************************************************************* HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, volatile uint8_t *ucsra, volatile uint8_t *ucsrb, @@ -129,6 +218,7 @@ HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, // Public Methods ////////////////////////////////////////////////////////////// +//******************************************************************************************* void HardwareSerial::begin(long baud) { uint16_t baud_setting; @@ -166,6 +256,7 @@ void HardwareSerial::begin(long baud) sbi(*_ucsrb, _rxcie); } +//******************************************************************************************* void HardwareSerial::end() { cbi(*_ucsrb, _rxen); @@ -173,11 +264,13 @@ void HardwareSerial::end() cbi(*_ucsrb, _rxcie); } +//******************************************************************************************* int HardwareSerial::available(void) { return (RX_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % RX_BUFFER_SIZE; } +//******************************************************************************************* int HardwareSerial::peek(void) { if (_rx_buffer->head == _rx_buffer->tail) { @@ -187,6 +280,7 @@ int HardwareSerial::peek(void) } } +//******************************************************************************************* int HardwareSerial::read(void) { // if the head isn't ahead of the tail, we don't have any characters @@ -199,6 +293,7 @@ int HardwareSerial::read(void) } } +//******************************************************************************************* void HardwareSerial::flush() { // don't reverse this or there may be problems if the RX interrupt @@ -213,6 +308,7 @@ void HardwareSerial::flush() _rx_buffer->head = _rx_buffer->tail; } +//******************************************************************************************* void HardwareSerial::write(uint8_t c) { while (!((*_ucsra) & (1 << _udre))) @@ -223,14 +319,27 @@ void HardwareSerial::write(uint8_t c) // Preinstantiate Objects ////////////////////////////////////////////////////// -#if defined(__AVR_ATmega8__) -HardwareSerial Serial(&rx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRE, U2X); +//#if defined(__AVR_ATmega8__) +#if defined(UBRRH) && defined(UBRRL) + HardwareSerial Serial(&rx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRE, U2X); +#elif defined(UBRR0H) && defined(UBRR0L) + HardwareSerial Serial(&rx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0, U2X0); +#elif defined(USBCON) + #warning no serial port defined (port 0) #else -HardwareSerial Serial(&rx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0, U2X0); + #error no serial port defined (port 0) #endif -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) -HardwareSerial Serial1(&rx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRE1, U2X1); -HardwareSerial Serial2(&rx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRE2, U2X2); -HardwareSerial Serial3(&rx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRE3, U2X3); +//#if defined(__AVR_ATmega1280__) +#if defined(UBRR1H) + HardwareSerial Serial1(&rx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRE1, U2X1); +#endif +#if defined(UBRR2H) + HardwareSerial Serial2(&rx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRE2, U2X2); +#endif +#if defined(UBRR3H) + HardwareSerial Serial3(&rx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRE3, U2X3); #endif + + +#endif //defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H) diff --git a/hardware/arduino/cores/arduino/HardwareSerial.h b/hardware/arduino/cores/arduino/HardwareSerial.h old mode 100755 new mode 100644 index 29898b9535a..dcb979f08d0 --- a/hardware/arduino/cores/arduino/HardwareSerial.h +++ b/hardware/arduino/cores/arduino/HardwareSerial.h @@ -16,6 +16,9 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +//******************************************************************************************* +//* Sep 28, 2010 <MLS> V0020 was released, migrated changes into 0020 +//******************************************************************************************* #ifndef HardwareSerial_h #define HardwareSerial_h @@ -56,12 +59,21 @@ class HardwareSerial : public Stream using Print::write; // pull in write(str) and write(buf, size) from Print }; -extern HardwareSerial Serial; +#if defined(UBRRH) || defined(UBRR0H) + extern HardwareSerial Serial; +#elif defined(USBCON) + #include "usb_api.h" +#endif -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) -extern HardwareSerial Serial1; -extern HardwareSerial Serial2; -extern HardwareSerial Serial3; +//#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#if defined(UBRR1H) + extern HardwareSerial Serial1; +#endif +#if defined(UBRR2H) + extern HardwareSerial Serial2; +#endif +#if defined(UBRR3H) + extern HardwareSerial Serial3; #endif #endif From 07787001bf9298edc18088ef9273f52ec59fe096 Mon Sep 17 00:00:00 2001 From: Mark Sproul <msproul@tiger3.engr.rutgers.edu> Date: Fri, 1 Oct 2010 09:27:54 -0400 Subject: [PATCH 2/6] Changed from cpu #ifdefs to register #ifdefs --- hardware/arduino/cores/arduino/wiring_analog.c | 10 ++++++++++ 1 file changed, 10 insertions(+) mode change 100755 => 100644 hardware/arduino/cores/arduino/wiring_analog.c diff --git a/hardware/arduino/cores/arduino/wiring_analog.c b/hardware/arduino/cores/arduino/wiring_analog.c old mode 100755 new mode 100644 index da0cf0781ad..d5164f8b3ee --- a/hardware/arduino/cores/arduino/wiring_analog.c +++ b/hardware/arduino/cores/arduino/wiring_analog.c @@ -21,12 +21,22 @@ $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ */ +//******************************************************************************************* +//* Jul 27, 2010 <MLS> = Mark Sproul msproul-at-skychariot.com +//* Jul 27, 2010 <MLS> Rewrite of analogWrite to better support various cpus +//* Jul 27, 2010 <MLS> Refactoring analogWrite() to test for register, not cpu, definitions. +//* Jul 28, 2010 <MLS> submited enhancment request #307 +//* Aug 3, 2010 <MLS> improved the #ifdefs, now compiles for atmega645 +//* Sep 5, 2010 <MLS> V0019 was released, migrated changes into 0019 +//* Sep 28, 2010 <MLS> V0020 was released, migrated changes into 0020 +//******************************************************************************************* #include "wiring_private.h" #include "pins_arduino.h" uint8_t analog_reference = DEFAULT; +//********************************************************************* void analogReference(uint8_t mode) { // can't actually set the register here because the default setting From 202e0741f33e81641cc21750226a6105d4f70e9c Mon Sep 17 00:00:00 2001 From: Mark Sproul <msproul@tiger3.engr.rutgers.edu> Date: Fri, 1 Oct 2010 09:30:46 -0400 Subject: [PATCH 3/6] Changed from cpu #ifdefs to register #ifdefs --- hardware/arduino/cores/arduino/wiring_analog.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/hardware/arduino/cores/arduino/wiring_analog.c b/hardware/arduino/cores/arduino/wiring_analog.c index d5164f8b3ee..02701998640 100644 --- a/hardware/arduino/cores/arduino/wiring_analog.c +++ b/hardware/arduino/cores/arduino/wiring_analog.c @@ -45,28 +45,34 @@ void analogReference(uint8_t mode) analog_reference = mode; } +//********************************************************************* int analogRead(uint8_t pin) { uint8_t low, high; #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) if (pin >= 54) pin -= 54; // allow for channel or pin numbers +#else + if (pin >= 14) pin -= 14; // allow for channel or pin numbers +#endif +#if 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); -#else - if (pin >= 14) pin -= 14; // allow for channel or pin numbers #endif // set the analog reference (high two bits of ADMUX) and select the // channel (low 4 bits). this also sets ADLAR (left-adjust result) // to 0 (the default). +#if defined(ADMUX) ADMUX = (analog_reference << 6) | (pin & 0x07); +#endif // without a delay, we seem to read from the wrong channel //delay(1); +#if defined(ADCSRA) && defined(ADCL) // start the conversion sbi(ADCSRA, ADSC); From c69279331f3b90d34945cc365b399881f194ed2c Mon Sep 17 00:00:00 2001 From: Mark Sproul <msproul@tiger3.engr.rutgers.edu> Date: Fri, 1 Oct 2010 10:25:06 -0400 Subject: [PATCH 4/6] changed from cpu #ifdefs to register #ifdefs --- .../arduino/cores/arduino/wiring_analog.c | 263 +++++++++++------- 1 file changed, 169 insertions(+), 94 deletions(-) diff --git a/hardware/arduino/cores/arduino/wiring_analog.c b/hardware/arduino/cores/arduino/wiring_analog.c index 02701998640..2703a8a8e78 100644 --- a/hardware/arduino/cores/arduino/wiring_analog.c +++ b/hardware/arduino/cores/arduino/wiring_analog.c @@ -83,17 +83,24 @@ int analogRead(uint8_t pin) // and ADCH until ADCH is read. reading ADCL second would // cause the results of each conversion to be discarded, // as ADCL and ADCH would be locked when it completed. - low = ADCL; - high = ADCH; + low = ADCL; + high = ADCH; +#else + //* we dont have an ADC, return 0 + low = 0; + high = 0; +#endif // combine the two bytes return (high << 8) | low; } +//********************************************************************* // Right now, PWM output only works on the pins with // hardware support. These are defined in the appropriate // pins_*.c file. For the rest of the pins, we default // to digital output. +//********************************************************************* void analogWrite(uint8_t pin, int val) { // We need to make sure the PWM output is enabled for those pins @@ -102,98 +109,166 @@ void analogWrite(uint8_t pin, int val) // for consistenty with Wiring, which doesn't require a pinMode // call for the analog output pins. pinMode(pin, OUTPUT); - - if (digitalPinToTimer(pin) == TIMER1A) { - // connect pwm to pin on timer 1, channel A - sbi(TCCR1A, COM1A1); - // set pwm duty - OCR1A = val; - } else if (digitalPinToTimer(pin) == TIMER1B) { - // connect pwm to pin on timer 1, channel B - sbi(TCCR1A, COM1B1); - // set pwm duty - OCR1B = val; -#if defined(__AVR_ATmega8__) - } else if (digitalPinToTimer(pin) == TIMER2) { - // connect pwm to pin on timer 2, channel B - sbi(TCCR2, COM21); - // set pwm duty - OCR2 = val; -#else - } else if (digitalPinToTimer(pin) == TIMER0A) { - if (val == 0) { - digitalWrite(pin, LOW); - } else { - // connect pwm to pin on timer 0, channel A - sbi(TCCR0A, COM0A1); - // set pwm duty - OCR0A = val; - } - } else if (digitalPinToTimer(pin) == TIMER0B) { - if (val == 0) { - digitalWrite(pin, LOW); - } else { - // connect pwm to pin on timer 0, channel B - sbi(TCCR0A, COM0B1); - // set pwm duty - OCR0B = val; - } - } else if (digitalPinToTimer(pin) == TIMER2A) { - // connect pwm to pin on timer 2, channel A - sbi(TCCR2A, COM2A1); - // set pwm duty - OCR2A = val; - } else if (digitalPinToTimer(pin) == TIMER2B) { - // connect pwm to pin on timer 2, channel B - sbi(TCCR2A, COM2B1); - // set pwm duty - OCR2B = val; -#endif -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) - // XXX: need to handle other timers here - } else if (digitalPinToTimer(pin) == TIMER3A) { - // connect pwm to pin on timer 3, channel A - sbi(TCCR3A, COM3A1); - // set pwm duty - OCR3A = val; - } else if (digitalPinToTimer(pin) == TIMER3B) { - // connect pwm to pin on timer 3, channel B - sbi(TCCR3A, COM3B1); - // set pwm duty - OCR3B = val; - } else if (digitalPinToTimer(pin) == TIMER3C) { - // connect pwm to pin on timer 3, channel C - sbi(TCCR3A, COM3C1); - // set pwm duty - OCR3C = val; - } else if (digitalPinToTimer(pin) == TIMER4A) { - // connect pwm to pin on timer 4, channel A - sbi(TCCR4A, COM4A1); - // set pwm duty - OCR4A = val; - } else if (digitalPinToTimer(pin) == TIMER4B) { - // connect pwm to pin on timer 4, channel B - sbi(TCCR4A, COM4B1); - // set pwm duty - OCR4B = val; - } else if (digitalPinToTimer(pin) == TIMER4C) { - // connect pwm to pin on timer 4, channel C - sbi(TCCR4A, COM4C1); - // set pwm duty - OCR4C = val; - } else if (digitalPinToTimer(pin) == TIMER5A) { - // connect pwm to pin on timer 5, channel A - sbi(TCCR5A, COM5A1); - // set pwm duty - OCR5A = val; - } else if (digitalPinToTimer(pin) == TIMER5B) { - // connect pwm to pin on timer 5, channel B - sbi(TCCR5A, COM5B1); - // set pwm duty - OCR5B = val; -#endif - } else if (val < 128) + if (val == 0) + { digitalWrite(pin, LOW); - else + } + else if (val == 255) + { digitalWrite(pin, HIGH); + } + else + { + switch(digitalPinToTimer(pin)) + { + #if defined(TCCR0) && defined(COM00) && !defined(__AVR_ATmega8__) + //* I need to fix this for atmega8 + case TIMER0A: + // connect pwm to pin on timer 0 + sbi(TCCR0, COM00); + OCR0 = val; // set pwm duty + break; + #endif + + #if defined(TCCR0A) && defined(COM0A1) + case TIMER0A: + // connect pwm to pin on timer 0, channel A + sbi(TCCR0A, COM0A1); + OCR0A = val; // set pwm duty + break; + #endif + + #if defined(TCCR0A) && defined(COM0B1) + case TIMER0B: + // connect pwm to pin on timer 0, channel B + sbi(TCCR0A, COM0B1); + OCR0B = val; // set pwm duty + break; + #endif + + #if defined(TCCR1A) && defined(COM1A1) + case TIMER1A: + // connect pwm to pin on timer 1, channel A + sbi(TCCR1A, COM1A1); + OCR1A = val; // set pwm duty + break; + #endif + + #if defined(TCCR1A) && defined(COM1B1) + case TIMER1B: + // connect pwm to pin on timer 1, channel B + sbi(TCCR1A, COM1B1); + OCR1B = val; // set pwm duty + break; + #endif + + #if defined(TCCR2) && defined(COM21) + case TIMER2: + // connect pwm to pin on timer 2, channel B + sbi(TCCR2, COM21); + OCR2 = val; // set pwm duty + break; + #endif + + #if defined(TCCR2A) && defined(COM2A1) + case TIMER2A: + // connect pwm to pin on timer 2, channel A + sbi(TCCR2A, COM2A1); + OCR2A = val; // set pwm duty + break; + #endif + + #if defined(TCCR2A) && defined(COM2B1) + case TIMER2B: + // connect pwm to pin on timer 2, channel B + sbi(TCCR2A, COM2B1); + OCR2B = val; // set pwm duty + break; + #endif + + #if defined(TCCR3A) && defined(COM3A1) + case TIMER3A: + // connect pwm to pin on timer 3, channel A + sbi(TCCR3A, COM3A1); + OCR3A = val; // set pwm duty + break; + #endif + + #if defined(TCCR3A) && defined(COM3B1) + case TIMER3B: + // connect pwm to pin on timer 3, channel B + sbi(TCCR3A, COM3B1); + OCR3B = val; // set pwm duty + break; + #endif + + #if defined(TCCR3A) && defined(COM3C1) + case TIMER3C: + // connect pwm to pin on timer 3, channel C + sbi(TCCR3A, COM3C1); + OCR3C = val; // set pwm duty + break; + #endif + + #if defined(TCCR4A) && defined(COM4A1) + case TIMER4A: + // connect pwm to pin on timer 4, channel A + sbi(TCCR4A, COM4A1); + OCR4A = val; // set pwm duty + break; + #endif + + #if defined(TCCR4A) && defined(COM4B1) + case TIMER4B: + // connect pwm to pin on timer 4, channel B + sbi(TCCR4A, COM4B1); + OCR4B = val; // set pwm duty + break; + #endif + + #if defined(TCCR4A) && defined(COM4C1) + case TIMER4C: + // connect pwm to pin on timer 4, channel C + sbi(TCCR4A, COM4C1); + OCR4C = val; // set pwm duty + break; + #endif + + #if defined(TCCR5A) && defined(COM5A1) + case TIMER5A: + // connect pwm to pin on timer 5, channel A + sbi(TCCR5A, COM5A1); + OCR5A = val; // set pwm duty + break; + #endif + + #if defined(TCCR5A) && defined(COM5B1) + case TIMER5B: + // connect pwm to pin on timer 5, channel B + sbi(TCCR5A, COM5B1); + OCR5B = val; // set pwm duty + break; + #endif + + //* Jul 27, 2010 <MLS> Added this, Its missing from the main core files + #if defined(TCCR5A) && defined(COM5C1) + case TIMER5C: + // connect pwm to pin on timer 5, channel C + sbi(TCCR5A, COM5C1); + OCR5C = val; // set pwm duty + break; + #endif + + case NOT_ON_TIMER: + default: + if (val < 128) + { + digitalWrite(pin, LOW); + } + else + { + digitalWrite(pin, HIGH); + } + } + } } From c5b85b328eab35382aedbb0529099473bd70ab05 Mon Sep 17 00:00:00 2001 From: Cristian Maglie <c.maglie@bug.st> Date: Tue, 5 Oct 2010 20:43:11 +0200 Subject: [PATCH 5/6] Added all Mark Sproul patches at once --- .../arduino/cores/arduino/HardwareSerial.cpp | 208 ++++++++---------- .../arduino/cores/arduino/HardwareSerial.h | 17 +- hardware/arduino/cores/arduino/WInterrupts.c | 44 +++- hardware/arduino/cores/arduino/wiring.c | 68 ++++-- hardware/arduino/cores/arduino/wiring.h | 15 +- .../arduino/cores/arduino/wiring_analog.c | 138 ++++++------ .../arduino/cores/arduino/wiring_digital.c | 80 ++++--- 7 files changed, 303 insertions(+), 267 deletions(-) diff --git a/hardware/arduino/cores/arduino/HardwareSerial.cpp b/hardware/arduino/cores/arduino/HardwareSerial.cpp index 28449f69bdf..84e9cb24082 100644 --- a/hardware/arduino/cores/arduino/HardwareSerial.cpp +++ b/hardware/arduino/cores/arduino/HardwareSerial.cpp @@ -17,18 +17,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Modified 23 November 2006 by David A. Mellis + Modified 28 September 2010 by Mark Sproul */ -//******************************************************************************************* -//* Mar 14, 2010 <MLS> Mark Sproul fixed bug in __AVR_ATmega644__ interrupt vector -//* Mar 25, 2010 <MLS> Fixed bug in __AVR_ATmega644P__ interrupt vector -//* Apr 2, 2010 <MLS> Changed RX_BUFFER_SIZE to 32 for smaller ram processors -//* Jul 30, 2010 <MLS> Chainging #ifdefs to register and signals instead of CPU type -//* Aug 3, 2010 <MLS> Tested on 644P 645 1280, 2560 328 and others -//* Aug 16, 2010 <MLS> Added support for Atmega32 -//* Aug 31, 2010 <MLS> The ATmega32U4 has uart1 but NOT uart0 -//* Sep 5, 2010 <MLS> V0019 was released, migrated changes into 0019 -//* Sep 28, 2010 <MLS> V0020 was released, migrated changes into 0020 -//******************************************************************************************* #include <stdlib.h> #include <stdio.h> @@ -37,9 +27,8 @@ #include "wiring.h" #include "wiring_private.h" -//******************************************************************************************* -//* this next line disables the entire HardwareSerial.cpp, -//* this is so I can support Attiny series and any other chip without a uart +// this next line disables the entire HardwareSerial.cpp, +// this is so I can support Attiny series and any other chip without a uart #if defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H) #include "HardwareSerial.h" @@ -49,34 +38,31 @@ // location to which to write the next incoming character and rx_buffer_tail // is the index of the location from which to read. #if (RAMEND < 1500) - #define RX_BUFFER_SIZE 32 + #define RX_BUFFER_SIZE 32 #else - #define RX_BUFFER_SIZE 128 + #define RX_BUFFER_SIZE 128 #endif struct ring_buffer { - unsigned char buffer[RX_BUFFER_SIZE]; - int head; - int tail; + unsigned char buffer[RX_BUFFER_SIZE]; + int head; + int tail; }; #if defined(UBRRH) || defined(UBRR0H) - ring_buffer rx_buffer = { { 0 }, 0, 0 }; + ring_buffer rx_buffer = { { 0 }, 0, 0 }; #endif - -//#if defined(__AVR_ATmega1280__) #if defined(UBRR1H) - ring_buffer rx_buffer1 = { { 0 }, 0, 0 }; + ring_buffer rx_buffer1 = { { 0 }, 0, 0 }; #endif #if defined(UBRR2H) - ring_buffer rx_buffer2 = { { 0 }, 0, 0 }; + ring_buffer rx_buffer2 = { { 0 }, 0, 0 }; #endif #if defined(UBRR3H) - ring_buffer rx_buffer3 = { { 0 }, 0, 0 }; + ring_buffer rx_buffer3 = { { 0 }, 0, 0 }; #endif -//******************************************************************************************* inline void store_char(unsigned char c, ring_buffer *rx_buffer) { int i = (rx_buffer->head + 1) % RX_BUFFER_SIZE; @@ -92,111 +78,98 @@ inline void store_char(unsigned char c, ring_buffer *rx_buffer) } #if defined(USART_RX_vect) -//******************************************************************************************* -SIGNAL(USART_RX_vect) -{ -#if defined(UDR0) - unsigned char c = UDR0; -#elif defined(UDR) - unsigned char c = UDR; // atmega8535 -#else - #error UDR not defined -#endif - store_char(c, &rx_buffer); -} + SIGNAL(USART_RX_vect) + { + #if defined(UDR0) + unsigned char c = UDR0; + #elif defined(UDR) + unsigned char c = UDR; // atmega8535 + #else + #error UDR not defined + #endif + store_char(c, &rx_buffer); + } #elif defined(SIG_USART0_RECV) && defined(UDR0) -//******************************************************************************************* -SIGNAL(SIG_USART0_RECV) -{ - unsigned char c = UDR0; - store_char(c, &rx_buffer); -} + SIGNAL(SIG_USART0_RECV) + { + unsigned char c = UDR0; + store_char(c, &rx_buffer); + } #elif defined(SIG_UART0_RECV) && defined(UDR0) -//******************************************************************************************* -SIGNAL(SIG_UART0_RECV) -{ - unsigned char c = UDR0; - store_char(c, &rx_buffer); -} + SIGNAL(SIG_UART0_RECV) + { + unsigned char c = UDR0; + store_char(c, &rx_buffer); + } //#elif defined(SIG_USART_RECV) #elif defined(USART0_RX_vect) -//******************************************************************************************* -//* fixed by Mark Sproul March 25, 2010 -//* this is on the 644/644p -//SIGNAL(SIG_USART_RECV) -SIGNAL(USART0_RX_vect) -{ -#if defined(UDR0) - unsigned char c = UDR0; -#elif defined(UDR) - unsigned char c = UDR; // atmega8, atmega32 -#else - #error UDR not defined -#endif - store_char(c, &rx_buffer); -} + // fixed by Mark Sproul this is on the 644/644p + //SIGNAL(SIG_USART_RECV) + SIGNAL(USART0_RX_vect) + { + #if defined(UDR0) + unsigned char c = UDR0; + #elif defined(UDR) + unsigned char c = UDR; // atmega8, atmega32 + #else + #error UDR not defined + #endif + store_char(c, &rx_buffer); + } #elif defined(SIG_UART_RECV) -//******************************************************************************************* -//* this is for atmega8 -SIGNAL(SIG_UART_RECV) -{ -#if defined(UDR0) - unsigned char c = UDR0; // atmega645 -#elif defined(UDR) - unsigned char c = UDR; // atmega8 -#endif - - store_char(c, &rx_buffer); -} + // this is for atmega8 + SIGNAL(SIG_UART_RECV) + { + #if defined(UDR0) + unsigned char c = UDR0; // atmega645 + #elif defined(UDR) + unsigned char c = UDR; // atmega8 + #endif + store_char(c, &rx_buffer); + } #elif defined(USBCON) - #warning No interrupt handler for usart 0 - #warning Serial(0) is on USB interface + #warning No interrupt handler for usart 0 + #warning Serial(0) is on USB interface #else - #error No interrupt handler for usart 0 + #error No interrupt handler for usart 0 #endif //#if defined(SIG_USART1_RECV) #if defined(USART1_RX_vect) -//******************************************************************************************* -//SIGNAL(SIG_USART1_RECV) -SIGNAL(USART1_RX_vect) -{ - unsigned char c = UDR1; - store_char(c, &rx_buffer1); -} + //SIGNAL(SIG_USART1_RECV) + SIGNAL(USART1_RX_vect) + { + unsigned char c = UDR1; + store_char(c, &rx_buffer1); + } #elif defined(SIG_USART1_RECV) - #error SIG_USART1_RECV + #error SIG_USART1_RECV #endif - -//#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) #if defined(USART2_RX_vect) -//******************************************************************************************* -SIGNAL(USART2_RX_vect) -{ - unsigned char c = UDR2; - store_char(c, &rx_buffer2); -} + SIGNAL(USART2_RX_vect) + { + unsigned char c = UDR2; + store_char(c, &rx_buffer2); + } #elif defined(SIG_USART2_RECV) - #error SIG_USART2_RECV + #error SIG_USART2_RECV #endif #if defined(USART3_RX_vect) -//******************************************************************************************* -SIGNAL(USART3_RX_vect) -{ - unsigned char c = UDR3; - store_char(c, &rx_buffer3); -} + SIGNAL(USART3_RX_vect) + { + unsigned char c = UDR3; + store_char(c, &rx_buffer3); + } #elif defined(SIG_USART3_RECV) - #error SIG_USART3_RECV + #error SIG_USART3_RECV #endif // Constructors //////////////////////////////////////////////////////////////// -//******************************************************************************************* HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, volatile uint8_t *ucsra, volatile uint8_t *ucsrb, @@ -218,7 +191,6 @@ HardwareSerial::HardwareSerial(ring_buffer *rx_buffer, // Public Methods ////////////////////////////////////////////////////////////// -//******************************************************************************************* void HardwareSerial::begin(long baud) { uint16_t baud_setting; @@ -256,7 +228,6 @@ void HardwareSerial::begin(long baud) sbi(*_ucsrb, _rxcie); } -//******************************************************************************************* void HardwareSerial::end() { cbi(*_ucsrb, _rxen); @@ -264,13 +235,11 @@ void HardwareSerial::end() cbi(*_ucsrb, _rxcie); } -//******************************************************************************************* int HardwareSerial::available(void) { return (RX_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % RX_BUFFER_SIZE; } -//******************************************************************************************* int HardwareSerial::peek(void) { if (_rx_buffer->head == _rx_buffer->tail) { @@ -280,7 +249,6 @@ int HardwareSerial::peek(void) } } -//******************************************************************************************* int HardwareSerial::read(void) { // if the head isn't ahead of the tail, we don't have any characters @@ -293,7 +261,6 @@ int HardwareSerial::read(void) } } -//******************************************************************************************* void HardwareSerial::flush() { // don't reverse this or there may be problems if the RX interrupt @@ -308,7 +275,6 @@ void HardwareSerial::flush() _rx_buffer->head = _rx_buffer->tail; } -//******************************************************************************************* void HardwareSerial::write(uint8_t c) { while (!((*_ucsra) & (1 << _udre))) @@ -319,27 +285,25 @@ void HardwareSerial::write(uint8_t c) // Preinstantiate Objects ////////////////////////////////////////////////////// -//#if defined(__AVR_ATmega8__) #if defined(UBRRH) && defined(UBRRL) - HardwareSerial Serial(&rx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRE, U2X); + HardwareSerial Serial(&rx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRE, U2X); #elif defined(UBRR0H) && defined(UBRR0L) - HardwareSerial Serial(&rx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0, U2X0); + HardwareSerial Serial(&rx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0, U2X0); #elif defined(USBCON) - #warning no serial port defined (port 0) + #warning no serial port defined (port 0) #else - #error no serial port defined (port 0) + #error no serial port defined (port 0) #endif -//#if defined(__AVR_ATmega1280__) #if defined(UBRR1H) - HardwareSerial Serial1(&rx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRE1, U2X1); + HardwareSerial Serial1(&rx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRE1, U2X1); #endif #if defined(UBRR2H) - HardwareSerial Serial2(&rx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRE2, U2X2); + HardwareSerial Serial2(&rx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRE2, U2X2); #endif #if defined(UBRR3H) - HardwareSerial Serial3(&rx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRE3, U2X3); + HardwareSerial Serial3(&rx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRE3, U2X3); #endif +#endif // whole file -#endif //defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H) diff --git a/hardware/arduino/cores/arduino/HardwareSerial.h b/hardware/arduino/cores/arduino/HardwareSerial.h index dcb979f08d0..3efa775f843 100644 --- a/hardware/arduino/cores/arduino/HardwareSerial.h +++ b/hardware/arduino/cores/arduino/HardwareSerial.h @@ -15,10 +15,9 @@ You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Modified 28 September 2010 by Mark Sproul */ -//******************************************************************************************* -//* Sep 28, 2010 <MLS> V0020 was released, migrated changes into 0020 -//******************************************************************************************* #ifndef HardwareSerial_h #define HardwareSerial_h @@ -60,20 +59,18 @@ class HardwareSerial : public Stream }; #if defined(UBRRH) || defined(UBRR0H) - extern HardwareSerial Serial; + extern HardwareSerial Serial; #elif defined(USBCON) - #include "usb_api.h" + #include "usb_api.h" #endif - -//#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) #if defined(UBRR1H) - extern HardwareSerial Serial1; + extern HardwareSerial Serial1; #endif #if defined(UBRR2H) - extern HardwareSerial Serial2; + extern HardwareSerial Serial2; #endif #if defined(UBRR3H) - extern HardwareSerial Serial3; + extern HardwareSerial Serial3; #endif #endif diff --git a/hardware/arduino/cores/arduino/WInterrupts.c b/hardware/arduino/cores/arduino/WInterrupts.c index 9c5741148ca..756cbcc89c2 100755 --- a/hardware/arduino/cores/arduino/WInterrupts.c +++ b/hardware/arduino/cores/arduino/WInterrupts.c @@ -21,6 +21,7 @@ Boston, MA 02111-1307 USA Modified 24 November 2006 by David A. Mellis + Modified 1 August 2010 by Mark Sproul */ #include <inttypes.h> @@ -35,11 +36,6 @@ volatile static voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS]; // volatile static voidFuncPtr twiIntFunc; -#if defined(__AVR_ATmega8__) -#define EICRA MCUCR -#define EIMSK GICR -#endif - void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) { if(interruptNum < EXTERNAL_NUM_INTERRUPTS) { intFunc[interruptNum] = userFunc; @@ -52,7 +48,7 @@ void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) { // Enable the interrupt. switch (interruptNum) { -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#if defined(EICRA) && defined(EICRB) case 2: EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00); EIMSK |= (1 << INT0); @@ -87,12 +83,29 @@ void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) { break; #else case 0: + #if defined(EICRA) && defined(ISC00) && defined(EIMSK) EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00); EIMSK |= (1 << INT0); + #elif defined(MCUCR) && defined(ISC00) + MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00); + GICR |= (1 << INT0); + #else + #error attachInterrupt not finished for this CPU (case 0) + #endif break; case 1: + #if defined(EICRA) && defined(ISC10) && defined(ISC11) && defined(EIMSK) EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10); EIMSK |= (1 << INT1); + #elif defined(MCUCR) && defined(ISC10) && defined(ISC11) && defined(GICR) + MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10); + GICR |= (1 << INT1); + #elif defined(__AVR_ATmega645__) || defined(__AVR_ATmega169__) + //* atmega645 and 169 dont have all of these control bits + #warning attachInterrupt may need some more work for this cpu (case 1) + #else + #error attachInterrupt not finished for this CPU (case 1) + #endif break; #endif } @@ -105,7 +118,7 @@ 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(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#if defined(EICRA) && defined(EICRB) case 2: EIMSK &= ~(1 << INT0); break; @@ -132,10 +145,25 @@ void detachInterrupt(uint8_t interruptNum) { break; #else case 0: + #if defined(EIMSK) && defined(INT0) EIMSK &= ~(1 << INT0); + #elif defined(GICR) && defined(ISC00) + GICR &= ~(1 << INT0); // atmega32 + #else + #error detachInterrupt not finished for this cpu + #endif break; case 1: + #if defined(EIMSK) && defined(INT1) EIMSK &= ~(1 << INT1); + #elif defined(GICR) && defined(ISC00) + GICR &= ~(1 << INT1); // atmega32 + #elif defined(__AVR_ATmega645__) || defined(__AVR_ATmega169__) + // atmega645 and 169 dont have all of these control bits + #warning detachInterrupt may need some more work for this cpu (case 1) + #else + #error detachInterrupt not finished for this cpu + #endif break; #endif } @@ -150,7 +178,7 @@ void attachInterruptTwi(void (*userFunc)(void) ) { } */ -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#if defined(EICRA) && defined(EICRB) SIGNAL(INT0_vect) { if(intFunc[EXTERNAL_INT_2]) diff --git a/hardware/arduino/cores/arduino/wiring.c b/hardware/arduino/cores/arduino/wiring.c index eb2d44001d4..82ef3fa3390 100755 --- a/hardware/arduino/cores/arduino/wiring.c +++ b/hardware/arduino/cores/arduino/wiring.c @@ -166,31 +166,44 @@ void init() // on the ATmega168, timer 0 is also used for fast hardware pwm // (using phase-correct PWM would mean that timer 0 overflowed half as often // resulting in different millis() behavior on the ATmega8 and ATmega168) -#if !defined(__AVR_ATmega8__) +#if defined(TCCR0A) && defined(WGM01) sbi(TCCR0A, WGM01); sbi(TCCR0A, WGM00); #endif + // set timer 0 prescale factor to 64 -#if defined(__AVR_ATmega8__) +#if defined(__AVR_ATmega128__) + // CPU specific: different values for the ATmega128 + sbi(TCCR0, CS02); +#elif defined(TCCR0) && defined(CS01) && defined(CS00) + // this combination is for the standard atmega8 sbi(TCCR0, CS01); sbi(TCCR0, CS00); -#else +#elif defined(TCCR0B) && defined(CS01) && defined(CS00) + // this combination is for the standard 168/328/1280/2560 sbi(TCCR0B, CS01); sbi(TCCR0B, CS00); +#elif defined(TCCR0A) && defined(CS01) && defined(CS00) + // this combination is for the __AVR_ATmega645__ series + sbi(TCCR0A, CS01); + sbi(TCCR0A, CS00); +#else + #error Timer 0 prescale factor 64 not set correctly #endif + // enable timer 0 overflow interrupt -#if defined(__AVR_ATmega8__) +#if defined(TIMSK) && defined(TOIE0) sbi(TIMSK, TOIE0); -#else +#elif defined(TIMSK0) && defined(TOIE0) sbi(TIMSK0, TOIE0); +#else + #error Timer 0 overflow interrupt not set correctly #endif // timers 1 and 2 are used for phase-correct hardware pwm // this is better for motors as it ensures an even waveform // note, however, that fast pwm mode can achieve a frequency of up // 8 MHz (with a 16 MHz clock) at 50% duty cycle - - TCCR1B = 0; // set timer 1 prescale factor to 64 sbi(TCCR1B, CS11); @@ -199,27 +212,36 @@ void init() sbi(TCCR1A, WGM10); // set timer 2 prescale factor to 64 -#if defined(__AVR_ATmega8__) +#if defined(TCCR2) && defined(CS22) sbi(TCCR2, CS22); -#else +#endif +#if defined(TCCR2B) && defined(CS22) sbi(TCCR2B, CS22); #endif // configure timer 2 for phase correct pwm (8-bit) -#if defined(__AVR_ATmega8__) +#if defined(TCCR2) && defined(WGM20) sbi(TCCR2, WGM20); -#else +#endif +#if defined(TCCR2A) && defined(WGM20) sbi(TCCR2A, WGM20); #endif -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) - // set timer 3, 4, 5 prescale factor to 64 - sbi(TCCR3B, CS31); sbi(TCCR3B, CS30); - sbi(TCCR4B, CS41); sbi(TCCR4B, CS40); - sbi(TCCR5B, CS51); sbi(TCCR5B, CS50); - // put timer 3, 4, 5 in 8-bit phase correct pwm mode - sbi(TCCR3A, WGM30); - sbi(TCCR4A, WGM40); - sbi(TCCR5A, WGM50); +#if defined(TCCR3B) && defined(CS31) && defined(WGM30) + sbi(TCCR3B, CS31); // set timer 3, 4, 5 prescale factor to 64 + sbi(TCCR3B, CS30); + sbi(TCCR3A, WGM30); // put timer 3, 4, 5 in 8-bit phase correct pwm mode +#endif + +#if defined(TCCR4B) && defined(CS41) && defined(WGM40) + sbi(TCCR4B, CS41); // set timer 3, 4, 5 prescale factor to 64 + sbi(TCCR4B, CS40); + sbi(TCCR4A, WGM40); // put timer 3, 4, 5 in 8-bit phase correct pwm mode +#endif + +#if defined(TCCR5B) && defined(CS51) && defined(WGM50) + sbi(TCCR5B, CS51); // set timer 3, 4, 5 prescale factor to 64 + sbi(TCCR5B, CS50); + sbi(TCCR5A, WGM50); // put timer 3, 4, 5 in 8-bit phase correct pwm mode #endif // set a2d prescale factor to 128 @@ -236,9 +258,9 @@ void init() // the bootloader connects pins 0 and 1 to the USART; disconnect them // here so they can be used as normal digital i/o; they will be // reconnected in Serial.begin() -#if defined(__AVR_ATmega8__) +#if defined(UCSRB) UCSRB = 0; -#else +#elif defined(UCSR0B) UCSR0B = 0; #endif -} \ No newline at end of file +} diff --git a/hardware/arduino/cores/arduino/wiring.h b/hardware/arduino/cores/arduino/wiring.h index 7245797e3af..eb4a7a2fdd4 100755 --- a/hardware/arduino/cores/arduino/wiring.h +++ b/hardware/arduino/cores/arduino/wiring.h @@ -84,9 +84,18 @@ extern "C"{ #define interrupts() sei() #define noInterrupts() cli() -#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) -#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() ) -#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() ) +// Mark Sproul: +// if the clock is not an even multiple of 1000000 the following causes drift +// for example with F_CPU == 14745600L +#if (F_CPU == 16000000L) || (F_CPU == 8000000L) || (F_CPU == 20000000L) + #define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) + #define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() ) + #define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() ) +#else + #define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) + #define clockCyclesToMicroseconds(a) ( (a * 1000L) / (F_CPU / 1000L) ) + #define microsecondsToClockCycles(a) (( (a) * (F_CPU / 1000) ) / 1000) +#endif #define lowByte(w) ((uint8_t) ((w) & 0xff)) #define highByte(w) ((uint8_t) ((w) >> 8)) diff --git a/hardware/arduino/cores/arduino/wiring_analog.c b/hardware/arduino/cores/arduino/wiring_analog.c index 2703a8a8e78..d2d72989b69 100644 --- a/hardware/arduino/cores/arduino/wiring_analog.c +++ b/hardware/arduino/cores/arduino/wiring_analog.c @@ -19,24 +19,16 @@ Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Modified 28 September 2010 by Mark Sproul + $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ */ -//******************************************************************************************* -//* Jul 27, 2010 <MLS> = Mark Sproul msproul-at-skychariot.com -//* Jul 27, 2010 <MLS> Rewrite of analogWrite to better support various cpus -//* Jul 27, 2010 <MLS> Refactoring analogWrite() to test for register, not cpu, definitions. -//* Jul 28, 2010 <MLS> submited enhancment request #307 -//* Aug 3, 2010 <MLS> improved the #ifdefs, now compiles for atmega645 -//* Sep 5, 2010 <MLS> V0019 was released, migrated changes into 0019 -//* Sep 28, 2010 <MLS> V0020 was released, migrated changes into 0020 -//******************************************************************************************* #include "wiring_private.h" #include "pins_arduino.h" uint8_t analog_reference = DEFAULT; -//********************************************************************* void analogReference(uint8_t mode) { // can't actually set the register here because the default setting @@ -45,7 +37,6 @@ void analogReference(uint8_t mode) analog_reference = mode; } -//********************************************************************* int analogRead(uint8_t pin) { uint8_t low, high; @@ -83,24 +74,22 @@ int analogRead(uint8_t pin) // and ADCH until ADCH is read. reading ADCL second would // cause the results of each conversion to be discarded, // as ADCL and ADCH would be locked when it completed. - low = ADCL; - high = ADCH; + low = ADCL; + high = ADCH; #else - //* we dont have an ADC, return 0 - low = 0; - high = 0; + // we dont have an ADC, return 0 + low = 0; + high = 0; #endif // combine the two bytes return (high << 8) | low; } -//********************************************************************* // Right now, PWM output only works on the pins with // hardware support. These are defined in the appropriate // pins_*.c file. For the rest of the pins, we default // to digital output. -//********************************************************************* void analogWrite(uint8_t pin, int val) { // We need to make sure the PWM output is enabled for those pins @@ -121,152 +110,149 @@ void analogWrite(uint8_t pin, int val) { switch(digitalPinToTimer(pin)) { - #if defined(TCCR0) && defined(COM00) && !defined(__AVR_ATmega8__) - //* I need to fix this for atmega8 + // XXX fix needed for atmega8 + #if defined(TCCR0) && defined(COM00) && !defined(__AVR_ATmega8__) case TIMER0A: // connect pwm to pin on timer 0 sbi(TCCR0, COM00); - OCR0 = val; // set pwm duty + OCR0 = val; // set pwm duty break; - #endif + #endif - #if defined(TCCR0A) && defined(COM0A1) + #if defined(TCCR0A) && defined(COM0A1) case TIMER0A: // connect pwm to pin on timer 0, channel A sbi(TCCR0A, COM0A1); - OCR0A = val; // set pwm duty + OCR0A = val; // set pwm duty break; - #endif + #endif - #if defined(TCCR0A) && defined(COM0B1) + #if defined(TCCR0A) && defined(COM0B1) case TIMER0B: // connect pwm to pin on timer 0, channel B sbi(TCCR0A, COM0B1); - OCR0B = val; // set pwm duty + OCR0B = val; // set pwm duty break; - #endif + #endif - #if defined(TCCR1A) && defined(COM1A1) + #if defined(TCCR1A) && defined(COM1A1) case TIMER1A: // connect pwm to pin on timer 1, channel A sbi(TCCR1A, COM1A1); - OCR1A = val; // set pwm duty + OCR1A = val; // set pwm duty break; - #endif + #endif - #if defined(TCCR1A) && defined(COM1B1) + #if defined(TCCR1A) && defined(COM1B1) case TIMER1B: // connect pwm to pin on timer 1, channel B sbi(TCCR1A, COM1B1); - OCR1B = val; // set pwm duty + OCR1B = val; // set pwm duty break; - #endif + #endif - #if defined(TCCR2) && defined(COM21) + #if defined(TCCR2) && defined(COM21) case TIMER2: // connect pwm to pin on timer 2, channel B sbi(TCCR2, COM21); - OCR2 = val; // set pwm duty + OCR2 = val; // set pwm duty break; - #endif + #endif - #if defined(TCCR2A) && defined(COM2A1) + #if defined(TCCR2A) && defined(COM2A1) case TIMER2A: // connect pwm to pin on timer 2, channel A sbi(TCCR2A, COM2A1); - OCR2A = val; // set pwm duty + OCR2A = val; // set pwm duty break; - #endif + #endif - #if defined(TCCR2A) && defined(COM2B1) + #if defined(TCCR2A) && defined(COM2B1) case TIMER2B: // connect pwm to pin on timer 2, channel B sbi(TCCR2A, COM2B1); - OCR2B = val; // set pwm duty + OCR2B = val; // set pwm duty break; - #endif + #endif - #if defined(TCCR3A) && defined(COM3A1) + #if defined(TCCR3A) && defined(COM3A1) case TIMER3A: // connect pwm to pin on timer 3, channel A sbi(TCCR3A, COM3A1); - OCR3A = val; // set pwm duty + OCR3A = val; // set pwm duty break; - #endif + #endif - #if defined(TCCR3A) && defined(COM3B1) + #if defined(TCCR3A) && defined(COM3B1) case TIMER3B: // connect pwm to pin on timer 3, channel B sbi(TCCR3A, COM3B1); - OCR3B = val; // set pwm duty + OCR3B = val; // set pwm duty break; - #endif + #endif - #if defined(TCCR3A) && defined(COM3C1) + #if defined(TCCR3A) && defined(COM3C1) case TIMER3C: // connect pwm to pin on timer 3, channel C sbi(TCCR3A, COM3C1); - OCR3C = val; // set pwm duty + OCR3C = val; // set pwm duty break; - #endif + #endif - #if defined(TCCR4A) && defined(COM4A1) + #if defined(TCCR4A) && defined(COM4A1) case TIMER4A: // connect pwm to pin on timer 4, channel A sbi(TCCR4A, COM4A1); - OCR4A = val; // set pwm duty + OCR4A = val; // set pwm duty break; - #endif + #endif - #if defined(TCCR4A) && defined(COM4B1) + #if defined(TCCR4A) && defined(COM4B1) case TIMER4B: // connect pwm to pin on timer 4, channel B sbi(TCCR4A, COM4B1); - OCR4B = val; // set pwm duty + OCR4B = val; // set pwm duty break; - #endif + #endif - #if defined(TCCR4A) && defined(COM4C1) + #if defined(TCCR4A) && defined(COM4C1) case TIMER4C: // connect pwm to pin on timer 4, channel C sbi(TCCR4A, COM4C1); - OCR4C = val; // set pwm duty + OCR4C = val; // set pwm duty break; - #endif + #endif - #if defined(TCCR5A) && defined(COM5A1) + #if defined(TCCR5A) && defined(COM5A1) case TIMER5A: // connect pwm to pin on timer 5, channel A sbi(TCCR5A, COM5A1); - OCR5A = val; // set pwm duty + OCR5A = val; // set pwm duty break; - #endif + #endif - #if defined(TCCR5A) && defined(COM5B1) + #if defined(TCCR5A) && defined(COM5B1) case TIMER5B: // connect pwm to pin on timer 5, channel B sbi(TCCR5A, COM5B1); - OCR5B = val; // set pwm duty + OCR5B = val; // set pwm duty break; - #endif + #endif - //* Jul 27, 2010 <MLS> Added this, Its missing from the main core files - #if defined(TCCR5A) && defined(COM5C1) + // Mark Sproul: added this, Its missing from the main core files + #if defined(TCCR5A) && defined(COM5C1) case TIMER5C: // connect pwm to pin on timer 5, channel C sbi(TCCR5A, COM5C1); - OCR5C = val; // set pwm duty + OCR5C = val; // set pwm duty break; - #endif + #endif case NOT_ON_TIMER: default: - if (val < 128) - { + if (val < 128) { digitalWrite(pin, LOW); - } - else - { + } else { digitalWrite(pin, HIGH); } } diff --git a/hardware/arduino/cores/arduino/wiring_digital.c b/hardware/arduino/cores/arduino/wiring_digital.c index 1475f0c0478..1542814ab1e 100755 --- a/hardware/arduino/cores/arduino/wiring_digital.c +++ b/hardware/arduino/cores/arduino/wiring_digital.c @@ -19,6 +19,8 @@ Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Modified 28 September 2010 by Mark Sproul + $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ */ @@ -56,32 +58,60 @@ void pinMode(uint8_t pin, uint8_t mode) // But shouldn't this be moved into pinMode? Seems silly to check and do on // each digitalread or write. // -static inline void turnOffPWM(uint8_t timer) __attribute__ ((always_inline)); -static inline void turnOffPWM(uint8_t timer) +// Mark Sproul: +// - Removed inline. Save 170 bytes on atmega1280 +// - changed to a switch statment; added 32 bytes but much easier to read and maintain. +// - Added more #ifdefs, now compiles for atmega645 +// +//static inline void turnOffPWM(uint8_t timer) __attribute__ ((always_inline)); +//static inline void turnOffPWM(uint8_t timer) +static void turnOffPWM(uint8_t timer) { - if (timer == TIMER1A) cbi(TCCR1A, COM1A1); - if (timer == TIMER1B) cbi(TCCR1A, COM1B1); - -#if defined(__AVR_ATmega8__) - if (timer == TIMER2) cbi(TCCR2, COM21); -#else - if (timer == TIMER0A) cbi(TCCR0A, COM0A1); - if (timer == TIMER0B) cbi(TCCR0A, COM0B1); - if (timer == TIMER2A) cbi(TCCR2A, COM2A1); - if (timer == TIMER2B) cbi(TCCR2A, COM2B1); -#endif - -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) - if (timer == TIMER3A) cbi(TCCR3A, COM3A1); - if (timer == TIMER3B) cbi(TCCR3A, COM3B1); - if (timer == TIMER3C) cbi(TCCR3A, COM3C1); - if (timer == TIMER4A) cbi(TCCR4A, COM4A1); - if (timer == TIMER4B) cbi(TCCR4A, COM4B1); - if (timer == TIMER4C) cbi(TCCR4A, COM4C1); - if (timer == TIMER5A) cbi(TCCR5A, COM5A1); - if (timer == TIMER5B) cbi(TCCR5A, COM5B1); - if (timer == TIMER5C) cbi(TCCR5A, COM5C1); -#endif + switch (timer) + { + #if defined(TCCR1A) && defined(COM1A1) + case TIMER1A: cbi(TCCR1A, COM1A1); break; + #endif + #if defined(TCCR1A) && defined(COM1B1) + case TIMER1B: cbi(TCCR1A, COM1B1); break; + #endif + + #if defined(TCCR2) && defined(COM21) + case TIMER2: cbi(TCCR2, COM21); break; + #endif + + #if defined(TCCR0A) && defined(COM0A1) + case TIMER0A: cbi(TCCR0A, COM0A1); break; + #endif + + #if defined(TIMER0B) && defined(COM0B1) + case TIMER0B: cbi(TCCR0A, COM0B1); break; + #endif + #if defined(TCCR2A) && defined(COM2A1) + case TIMER2A: cbi(TCCR2A, COM2A1); break; + #endif + #if defined(TCCR2A) && defined(COM2B1) + case TIMER2B: cbi(TCCR2A, COM2B1); break; + #endif + + #if defined(TCCR3A) + case TIMER3A: cbi(TCCR3A, COM3A1); break; + case TIMER3B: cbi(TCCR3A, COM3B1); break; + case TIMER3C: cbi(TCCR3A, COM3C1); break; + + #endif + #if defined(TCCR4A) + case TIMER4A: cbi(TCCR4A, COM4A1); break; + case TIMER4B: cbi(TCCR4A, COM4B1); break; + case TIMER4C: cbi(TCCR4A, COM4C1); break; + + #endif + #if defined(TCCR5A) + case TIMER5A: cbi(TCCR5A, COM5A1); break; + case TIMER5B: cbi(TCCR5A, COM5B1); break; + case TIMER5C: cbi(TCCR5A, COM5C1); break; + #endif + } } void digitalWrite(uint8_t pin, uint8_t val) From 6062c4025dd876e84dca3e9754d0c02531a512bc Mon Sep 17 00:00:00 2001 From: Cristian Maglie <c.maglie@bug.st> Date: Tue, 12 Oct 2010 00:09:05 +0200 Subject: [PATCH 6/6] Merged Mark Sproul patches all at once (part two...) --- .../arduino/cores/arduino/HardwareSerial.cpp | 4 +- hardware/arduino/cores/arduino/Tone.cpp | 119 +++++++++++++++--- hardware/arduino/cores/arduino/WInterrupts.c | 38 +++--- hardware/arduino/cores/arduino/wiring.c | 31 ++++- .../arduino/cores/arduino/wiring_digital.c | 15 ++- 5 files changed, 161 insertions(+), 46 deletions(-) diff --git a/hardware/arduino/cores/arduino/HardwareSerial.cpp b/hardware/arduino/cores/arduino/HardwareSerial.cpp index 84e9cb24082..c50aaff441d 100644 --- a/hardware/arduino/cores/arduino/HardwareSerial.cpp +++ b/hardware/arduino/cores/arduino/HardwareSerial.cpp @@ -146,7 +146,7 @@ inline void store_char(unsigned char c, ring_buffer *rx_buffer) #error SIG_USART1_RECV #endif -#if defined(USART2_RX_vect) +#if defined(USART2_RX_vect) && defined(UDR2) SIGNAL(USART2_RX_vect) { unsigned char c = UDR2; @@ -156,7 +156,7 @@ inline void store_char(unsigned char c, ring_buffer *rx_buffer) #error SIG_USART2_RECV #endif -#if defined(USART3_RX_vect) +#if defined(USART3_RX_vect) && defined(UDR3) SIGNAL(USART3_RX_vect) { unsigned char c = UDR3; diff --git a/hardware/arduino/cores/arduino/Tone.cpp b/hardware/arduino/cores/arduino/Tone.cpp index 3ea034bf98b..8bdc5f7710e 100755 --- a/hardware/arduino/cores/arduino/Tone.cpp +++ b/hardware/arduino/cores/arduino/Tone.cpp @@ -28,7 +28,7 @@ Version Modified By Date Comments 09/11/25 Changed pin toggle method to XOR 09/11/25 Fixed timer0 from being excluded 0006 D Mellis 09/12/29 Replaced objects with functions - +0007 M Sproul 10/08/29 Changed #ifdefs from cpu to register *************************************************/ #include <avr/interrupt.h> @@ -36,7 +36,7 @@ Version Modified By Date Comments #include "wiring.h" #include "pins_arduino.h" -#if defined(__AVR_ATmega8__) +#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__) #define TCCR2A TCCR2 #define TCCR2B TCCR2 #define COM2A1 COM21 @@ -66,19 +66,26 @@ volatile long timer2_toggle_count; volatile uint8_t *timer2_pin_port; volatile uint8_t timer2_pin_mask; -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#if defined(TIMSK3) volatile long timer3_toggle_count; volatile uint8_t *timer3_pin_port; volatile uint8_t timer3_pin_mask; +#endif + +#if defined(TIMSK4) volatile long timer4_toggle_count; volatile uint8_t *timer4_pin_port; volatile uint8_t timer4_pin_mask; +#endif + +#if defined(TIMSK5) volatile long timer5_toggle_count; volatile uint8_t *timer5_pin_port; volatile uint8_t timer5_pin_mask; #endif +// MLS: This does not make sense, the 3 options are the same #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) #define AVAILABLE_TONE_PINS 1 @@ -133,7 +140,7 @@ static int8_t toneBegin(uint8_t _pin) // whereas 16 bit timers are set to either ck/1 or ck/64 prescalar switch (_timer) { -#if !defined(__AVR_ATmega8__) + #if defined(TCCR0A) && defined(TCCR0B) case 0: // 8 bit timer TCCR0A = 0; @@ -143,8 +150,9 @@ static int8_t toneBegin(uint8_t _pin) timer0_pin_port = portOutputRegister(digitalPinToPort(_pin)); timer0_pin_mask = digitalPinToBitMask(_pin); break; -#endif + #endif + #if defined(TCCR1A) && defined(TCCR1B) && defined(WGM12) case 1: // 16 bit timer TCCR1A = 0; @@ -154,6 +162,9 @@ static int8_t toneBegin(uint8_t _pin) timer1_pin_port = portOutputRegister(digitalPinToPort(_pin)); timer1_pin_mask = digitalPinToBitMask(_pin); break; + #endif + + #if defined(TCCR2A) && defined(TCCR2B) case 2: // 8 bit timer TCCR2A = 0; @@ -163,8 +174,9 @@ static int8_t toneBegin(uint8_t _pin) timer2_pin_port = portOutputRegister(digitalPinToPort(_pin)); timer2_pin_mask = digitalPinToBitMask(_pin); break; + #endif -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) + #if defined(TCCR3A) && defined(TCCR3B) && defined(TIMSK3) case 3: // 16 bit timer TCCR3A = 0; @@ -174,15 +186,27 @@ static int8_t toneBegin(uint8_t _pin) timer3_pin_port = portOutputRegister(digitalPinToPort(_pin)); timer3_pin_mask = digitalPinToBitMask(_pin); break; + #endif + + #if defined(TCCR4A) && defined(TCCR4B) && defined(TIMSK4) case 4: // 16 bit timer TCCR4A = 0; TCCR4B = 0; - bitWrite(TCCR4B, WGM42, 1); + #if defined(WGM42) + bitWrite(TCCR4B, WGM42, 1); + #elif defined(CS43) + #warning this may not be correct + // atmega32u4 + bitWrite(TCCR4B, CS43, 1); + #endif bitWrite(TCCR4B, CS40, 1); timer4_pin_port = portOutputRegister(digitalPinToPort(_pin)); timer4_pin_mask = digitalPinToBitMask(_pin); break; + #endif + + #if defined(TCCR5A) && defined(TCCR5B) && defined(TIMSK5) case 5: // 16 bit timer TCCR5A = 0; @@ -192,7 +216,7 @@ static int8_t toneBegin(uint8_t _pin) timer5_pin_port = portOutputRegister(digitalPinToPort(_pin)); timer5_pin_mask = digitalPinToBitMask(_pin); break; -#endif + #endif } } @@ -258,12 +282,22 @@ void tone(uint8_t _pin, unsigned int frequency, unsigned long duration) } } -#if !defined(__AVR_ATmega8__) +#if defined(TCCR0B) if (_timer == 0) + { TCCR0B = prescalarbits; + } else #endif +#if defined(TCCR2B) + { TCCR2B = prescalarbits; + } +#else + { + // dummy place holder to make the above ifdefs work + } +#endif } else { @@ -278,12 +312,20 @@ void tone(uint8_t _pin, unsigned int frequency, unsigned long duration) } if (_timer == 1) + { +#if defined(TCCR1B) TCCR1B = (TCCR1B & 0b11111000) | prescalarbits; -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#endif + } +#if defined(TCCR3B) else if (_timer == 3) TCCR3B = (TCCR3B & 0b11111000) | prescalarbits; +#endif +#if defined(TCCR4B) else if (_timer == 4) TCCR4B = (TCCR4B & 0b11111000) | prescalarbits; +#endif +#if defined(TCCR5B) else if (_timer == 5) TCCR5B = (TCCR5B & 0b11111000) | prescalarbits; #endif @@ -307,7 +349,7 @@ void tone(uint8_t _pin, unsigned int frequency, unsigned long duration) switch (_timer) { -#if !defined(__AVR_ATmega8__) +#if defined(OCR0A) && defined(TIMSK0) && defined(OCIE0A) case 0: OCR0A = ocr; timer0_toggle_count = toggle_count; @@ -316,27 +358,43 @@ void tone(uint8_t _pin, unsigned int frequency, unsigned long duration) #endif case 1: +#if defined(OCR1A) && defined(TIMSK1) && defined(OCIE1A) OCR1A = ocr; timer1_toggle_count = toggle_count; bitWrite(TIMSK1, OCIE1A, 1); +#elif defined(OCR1A) && defined(TIMSK) && defined(OCIE1A) + // this combination is for at least the ATmega32 + OCR1A = ocr; + timer1_toggle_count = toggle_count; + bitWrite(TIMSK, OCIE1A, 1); +#endif break; + +#if defined(OCR2A) && defined(TIMSK2) && defined(OCIE2A) case 2: OCR2A = ocr; timer2_toggle_count = toggle_count; bitWrite(TIMSK2, OCIE2A, 1); break; +#endif -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#if defined(TIMSK3) case 3: OCR3A = ocr; timer3_toggle_count = toggle_count; bitWrite(TIMSK3, OCIE3A, 1); break; +#endif + +#if defined(TIMSK4) case 4: OCR4A = ocr; timer4_toggle_count = toggle_count; bitWrite(TIMSK4, OCIE4A, 1); break; +#endif + +#if defined(OCR5A) && defined(TIMSK5) && defined(OCIE5A) case 5: OCR5A = ocr; timer5_toggle_count = toggle_count; @@ -356,27 +414,48 @@ void disableTimer(uint8_t _timer) { switch (_timer) { -#if !defined(__AVR_ATmega8__) case 0: - TIMSK0 = 0; + #if defined(TIMSK0) + TIMSK0 = 0; + #elif defined(TIMSK) + TIMSK = 0; // atmega32 + #endif break; -#endif + +#if defined(TIMSK1) && defined(OCIE1A) case 1: bitWrite(TIMSK1, OCIE1A, 0); break; +#endif + case 2: - bitWrite(TIMSK2, OCIE2A, 0); // disable interrupt - TCCR2A = (1 << WGM20); - TCCR2B = (TCCR2B & 0b11111000) | (1 << CS22); - OCR2A = 0; + #if defined(TIMSK2) && defined(OCIE2A) + bitWrite(TIMSK2, OCIE2A, 0); // disable interrupt + #endif + #if defined(TCCR2A) && defined(WGM20) + TCCR2A = (1 << WGM20); + #endif + #if defined(TCCR2B) && defined(CS22) + TCCR2B = (TCCR2B & 0b11111000) | (1 << CS22); + #endif + #if defined(OCR2A) + OCR2A = 0; + #endif break; -#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) + +#if defined(TIMSK3) case 3: TIMSK3 = 0; break; +#endif + +#if defined(TIMSK4) case 4: TIMSK4 = 0; break; +#endif + +#if defined(TIMSK5) case 5: TIMSK5 = 0; break; diff --git a/hardware/arduino/cores/arduino/WInterrupts.c b/hardware/arduino/cores/arduino/WInterrupts.c index 756cbcc89c2..3b3e0c9ec43 100755 --- a/hardware/arduino/cores/arduino/WInterrupts.c +++ b/hardware/arduino/cores/arduino/WInterrupts.c @@ -48,7 +48,7 @@ void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) { // Enable the interrupt. switch (interruptNum) { -#if defined(EICRA) && defined(EICRB) +#if defined(EICRA) && defined(EICRB) && defined(EIMSK) case 2: EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00); EIMSK |= (1 << INT0); @@ -86,25 +86,29 @@ void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) { #if defined(EICRA) && defined(ISC00) && defined(EIMSK) EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00); EIMSK |= (1 << INT0); - #elif defined(MCUCR) && defined(ISC00) - MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00); - GICR |= (1 << INT0); + #elif defined(MCUCR) && defined(ISC00) && defined(GICR) + MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00); + GICR |= (1 << INT0); + #elif defined(MCUCR) && defined(ISC00) && defined(GIMSK) + MCUCR = (MCUCR & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00); + GIMSK |= (1 << INT0); #else #error attachInterrupt not finished for this CPU (case 0) #endif break; + case 1: #if defined(EICRA) && defined(ISC10) && defined(ISC11) && defined(EIMSK) EICRA = (EICRA & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10); EIMSK |= (1 << INT1); #elif defined(MCUCR) && defined(ISC10) && defined(ISC11) && defined(GICR) - MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10); - GICR |= (1 << INT1); - #elif defined(__AVR_ATmega645__) || defined(__AVR_ATmega169__) - //* atmega645 and 169 dont have all of these control bits - #warning attachInterrupt may need some more work for this cpu (case 1) + MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10); + GICR |= (1 << INT1); + #elif defined(MCUCR) && defined(ISC10) && defined(GIMSK) && defined(GIMSK) + MCUCR = (MCUCR & ~((1 << ISC10) | (1 << ISC11))) | (mode << ISC10); + GIMSK |= (1 << INT1); #else - #error attachInterrupt not finished for this CPU (case 1) + #warning attachInterrupt may need some more work for this cpu (case 1) #endif break; #endif @@ -118,7 +122,7 @@ 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) +#if defined(EICRA) && defined(EICRB) && defined(EIMSK) case 2: EIMSK &= ~(1 << INT0); break; @@ -149,20 +153,22 @@ void detachInterrupt(uint8_t interruptNum) { EIMSK &= ~(1 << INT0); #elif defined(GICR) && defined(ISC00) GICR &= ~(1 << INT0); // atmega32 + #elif defined(GIMSK) && defined(INT0) + GIMSK &= ~(1 << INT0); #else #error detachInterrupt not finished for this cpu #endif break; + case 1: #if defined(EIMSK) && defined(INT1) EIMSK &= ~(1 << INT1); - #elif defined(GICR) && defined(ISC00) + #elif defined(GICR) && defined(INT1) GICR &= ~(1 << INT1); // atmega32 - #elif defined(__AVR_ATmega645__) || defined(__AVR_ATmega169__) - // atmega645 and 169 dont have all of these control bits - #warning detachInterrupt may need some more work for this cpu (case 1) + #elif defined(GIMSK) && defined(INT1) + GIMSK &= ~(1 << INT1); #else - #error detachInterrupt not finished for this cpu + #warning detachInterrupt may need some more work for this cpu (case 1) #endif break; #endif diff --git a/hardware/arduino/cores/arduino/wiring.c b/hardware/arduino/cores/arduino/wiring.c index 82ef3fa3390..ea54aee0308 100755 --- a/hardware/arduino/cores/arduino/wiring.c +++ b/hardware/arduino/cores/arduino/wiring.c @@ -80,7 +80,14 @@ unsigned long micros() { cli(); m = timer0_overflow_count; +#if defined(TCNT0) t = TCNT0; +#elif defined(TCNT0L) + t = TCNT0L; +#else + #error TIMER 0 not defined +#endif + #ifdef TIFR0 if ((TIFR0 & _BV(TOV0)) && (t < 255)) @@ -205,25 +212,39 @@ void init() // note, however, that fast pwm mode can achieve a frequency of up // 8 MHz (with a 16 MHz clock) at 50% duty cycle + TCCR1B = 0; + // set timer 1 prescale factor to 64 +#if defined(TCCR1B) && defined(CS11) && defined(CS10) sbi(TCCR1B, CS11); sbi(TCCR1B, CS10); +#elif defined(TCCR1) && defined(CS11) && defined(CS10) + sbi(TCCR1, CS11); + sbi(TCCR1, CS10); +#endif // put timer 1 in 8-bit phase correct pwm mode +#if defined(TCCR1A) && defined(WGM10) sbi(TCCR1A, WGM10); +#elif defined(TCCR1) + #warning this needs to be finished +#endif // set timer 2 prescale factor to 64 #if defined(TCCR2) && defined(CS22) sbi(TCCR2, CS22); -#endif -#if defined(TCCR2B) && defined(CS22) +#elif defined(TCCR2B) && defined(CS22) sbi(TCCR2B, CS22); +#else + #warning Timer 2 not finished (may not be present on this CPU) #endif + // configure timer 2 for phase correct pwm (8-bit) #if defined(TCCR2) && defined(WGM20) sbi(TCCR2, WGM20); -#endif -#if defined(TCCR2A) && defined(WGM20) +#elif defined(TCCR2A) && defined(WGM20) sbi(TCCR2A, WGM20); +#else + #warning Timer 2 not finished (may not be present on this CPU) #endif #if defined(TCCR3B) && defined(CS31) && defined(WGM30) @@ -244,6 +265,7 @@ void init() sbi(TCCR5A, WGM50); // put timer 3, 4, 5 in 8-bit phase correct pwm mode #endif +#if defined(ADCSRA) // set a2d prescale factor to 128 // 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range. // XXX: this will not work properly for other clock speeds, and @@ -254,6 +276,7 @@ void init() // enable a2d conversions sbi(ADCSRA, ADEN); +#endif // the bootloader connects pins 0 and 1 to the USART; disconnect them // here so they can be used as normal digital i/o; they will be diff --git a/hardware/arduino/cores/arduino/wiring_digital.c b/hardware/arduino/cores/arduino/wiring_digital.c index 1542814ab1e..0949da42d73 100755 --- a/hardware/arduino/cores/arduino/wiring_digital.c +++ b/hardware/arduino/cores/arduino/wiring_digital.c @@ -94,17 +94,24 @@ static void turnOffPWM(uint8_t timer) case TIMER2B: cbi(TCCR2A, COM2B1); break; #endif - #if defined(TCCR3A) + #if defined(TCCR3A) && defined(COM3A1) case TIMER3A: cbi(TCCR3A, COM3A1); break; + #endif + #if defined(TCCR3A) && defined(COM3B1) case TIMER3B: cbi(TCCR3A, COM3B1); break; + #endif + #if defined(TCCR3A) && defined(COM3C1) case TIMER3C: cbi(TCCR3A, COM3C1); break; - #endif - #if defined(TCCR4A) + + #if defined(TCCR4A) && defined(COM4A1) case TIMER4A: cbi(TCCR4A, COM4A1); break; + #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 #if defined(TCCR5A) case TIMER5A: cbi(TCCR5A, COM5A1); break;