From 3696fa044687542ee6b4a9bc488348e184ee3ae2 Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Fri, 11 Feb 2011 17:53:24 -0500 Subject: Optimized digitalWrite(), etc. from Alvaro Lopez. --- cores/arduino/wiring_digital.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) (limited to 'cores/arduino/wiring_digital.c') diff --git a/cores/arduino/wiring_digital.c b/cores/arduino/wiring_digital.c index 0949da4..95666b1 100755 --- a/cores/arduino/wiring_digital.c +++ b/cores/arduino/wiring_digital.c @@ -27,7 +27,7 @@ #include "wiring_private.h" #include "pins_arduino.h" -void pinMode(uint8_t pin, uint8_t mode) +void pinMode_lookup(uint8_t pin, uint8_t mode) { uint8_t bit = digitalPinToBitMask(pin); uint8_t port = digitalPinToPort(pin); @@ -121,7 +121,23 @@ static void turnOffPWM(uint8_t timer) } } -void digitalWrite(uint8_t pin, uint8_t val) +void __digitalWriteOR_locked(volatile uint8_t*out, uint8_t bit) +{ + uint8_t oldSREG = SREG; + cli(); + *out |= bit; + SREG=oldSREG; +} + +void __digitalWriteAND_locked(volatile uint8_t*out, uint8_t bit) +{ + uint8_t oldSREG = SREG; + cli(); + *out &= bit; // NOTE - no inversion here, invert before calling!!! + SREG=oldSREG; +} + +void digitalWrite_lookup(uint8_t pin, uint8_t val) { uint8_t timer = digitalPinToTimer(pin); uint8_t bit = digitalPinToBitMask(pin); @@ -136,20 +152,19 @@ void digitalWrite(uint8_t pin, uint8_t val) out = portOutputRegister(port); + uint8_t oldSREG = SREG; + cli(); + if (val == LOW) { - uint8_t oldSREG = SREG; - cli(); *out &= ~bit; - SREG = oldSREG; } else { - uint8_t oldSREG = SREG; - cli(); *out |= bit; - SREG = oldSREG; } + + SREG = oldSREG; } -int digitalRead(uint8_t pin) +int digitalRead_lookup(uint8_t pin) { uint8_t timer = digitalPinToTimer(pin); uint8_t bit = digitalPinToBitMask(pin); -- cgit v1.2.3-18-g5258 From eed15e48d68d10426e015515ec4143849739f2de Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Fri, 11 Feb 2011 19:29:46 -0500 Subject: Changes to optimized digitalWrte(), etc. Factoring out the implementation of digitalWrite(), digitalRead(), and pinMode() into macros that can either be inlined (for constant pin numbers) or executed within a function (non-constant pins). Removing testing for timers on pins in digitalWrite(), digitalRead(), and pinMode(). Moving pin to port macros from pins_arduino.h to wiring.h. --- cores/arduino/wiring_digital.c | 76 +++--------------------------------------- 1 file changed, 4 insertions(+), 72 deletions(-) (limited to 'cores/arduino/wiring_digital.c') diff --git a/cores/arduino/wiring_digital.c b/cores/arduino/wiring_digital.c index 95666b1..9671045 100755 --- a/cores/arduino/wiring_digital.c +++ b/cores/arduino/wiring_digital.c @@ -27,28 +27,9 @@ #include "wiring_private.h" #include "pins_arduino.h" -void pinMode_lookup(uint8_t pin, uint8_t mode) +void pinMode_lookup(uint8_t pin, uint8_t val) { - uint8_t bit = digitalPinToBitMask(pin); - uint8_t port = digitalPinToPort(pin); - volatile uint8_t *reg; - - if (port == NOT_A_PIN) return; - - // JWS: can I let the optimizer do this? - reg = portModeRegister(port); - - if (mode == INPUT) { - uint8_t oldSREG = SREG; - cli(); - *reg &= ~bit; - SREG = oldSREG; - } else { - uint8_t oldSREG = SREG; - cli(); - *reg |= bit; - SREG = oldSREG; - } + pinMode_implementation(pin, val); } // Forcing this inline keeps the callers from having to push their own stuff @@ -121,61 +102,12 @@ static void turnOffPWM(uint8_t timer) } } -void __digitalWriteOR_locked(volatile uint8_t*out, uint8_t bit) -{ - uint8_t oldSREG = SREG; - cli(); - *out |= bit; - SREG=oldSREG; -} - -void __digitalWriteAND_locked(volatile uint8_t*out, uint8_t bit) -{ - uint8_t oldSREG = SREG; - cli(); - *out &= bit; // NOTE - no inversion here, invert before calling!!! - SREG=oldSREG; -} - void digitalWrite_lookup(uint8_t pin, uint8_t val) { - uint8_t timer = digitalPinToTimer(pin); - uint8_t bit = digitalPinToBitMask(pin); - uint8_t port = digitalPinToPort(pin); - volatile uint8_t *out; - - if (port == NOT_A_PIN) return; - - // If the pin that support PWM output, we need to turn it off - // before doing a digital write. - if (timer != NOT_ON_TIMER) turnOffPWM(timer); - - out = portOutputRegister(port); - - uint8_t oldSREG = SREG; - cli(); - - if (val == LOW) { - *out &= ~bit; - } else { - *out |= bit; - } - - SREG = oldSREG; + digitalWrite_implementation(pin, val); } int digitalRead_lookup(uint8_t pin) { - uint8_t timer = digitalPinToTimer(pin); - uint8_t bit = digitalPinToBitMask(pin); - uint8_t port = digitalPinToPort(pin); - - if (port == NOT_A_PIN) return LOW; - - // If the pin that support PWM output, we need to turn it off - // before getting a digital reading. - if (timer != NOT_ON_TIMER) turnOffPWM(timer); - - if (*portInputRegister(port) & bit) return HIGH; - return LOW; + digitalRead_implementation(pin); } -- cgit v1.2.3-18-g5258 From cd050d05d1fa7ae87da68574a9e50edf6ac1ed8f Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Sat, 12 Feb 2011 14:47:08 -0500 Subject: Adding noAnalogWrite() function to disable PWM. Also, removing the inline version of digitalPinToTimer() (since we're not optimizing the functions that use it anyway). The noAnalogWrite() function is in wiring_analog.c, deriving from the previous turnOffPWM() which has moved from wiring_digital.c. http://code.google.com/p/arduino/issues/detail?id=476 --- cores/arduino/wiring_digital.c | 70 ------------------------------------------ 1 file changed, 70 deletions(-) (limited to 'cores/arduino/wiring_digital.c') diff --git a/cores/arduino/wiring_digital.c b/cores/arduino/wiring_digital.c index 9671045..20930c5 100755 --- a/cores/arduino/wiring_digital.c +++ b/cores/arduino/wiring_digital.c @@ -32,76 +32,6 @@ void pinMode_lookup(uint8_t pin, uint8_t val) pinMode_implementation(pin, val); } -// Forcing this inline keeps the callers from having to push their own stuff -// on the stack. It is a good performance win and only takes 1 more byte per -// user than calling. (It will take more bytes on the 168.) -// -// But shouldn't this be moved into pinMode? Seems silly to check and do on -// each digitalread or write. -// -// 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) -{ - 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) && 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) && 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; - case TIMER5B: cbi(TCCR5A, COM5B1); break; - case TIMER5C: cbi(TCCR5A, COM5C1); break; - #endif - } -} - void digitalWrite_lookup(uint8_t pin, uint8_t val) { digitalWrite_implementation(pin, val); -- cgit v1.2.3-18-g5258 From 63515122ca28d9a60e6aba2948fb01765ca1138e Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Fri, 18 Feb 2011 10:40:56 -0500 Subject: Revert "Adding noAnalogWrite() function to disable PWM." This reverts commit 38d4a34fec6925b29a732d13e200f54ee4b42025. --- cores/arduino/wiring_digital.c | 70 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) (limited to 'cores/arduino/wiring_digital.c') diff --git a/cores/arduino/wiring_digital.c b/cores/arduino/wiring_digital.c index 20930c5..9671045 100755 --- a/cores/arduino/wiring_digital.c +++ b/cores/arduino/wiring_digital.c @@ -32,6 +32,76 @@ void pinMode_lookup(uint8_t pin, uint8_t val) pinMode_implementation(pin, val); } +// Forcing this inline keeps the callers from having to push their own stuff +// on the stack. It is a good performance win and only takes 1 more byte per +// user than calling. (It will take more bytes on the 168.) +// +// But shouldn't this be moved into pinMode? Seems silly to check and do on +// each digitalread or write. +// +// 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) +{ + 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) && 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) && 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; + case TIMER5B: cbi(TCCR5A, COM5B1); break; + case TIMER5C: cbi(TCCR5A, COM5C1); break; + #endif + } +} + void digitalWrite_lookup(uint8_t pin, uint8_t val) { digitalWrite_implementation(pin, val); -- cgit v1.2.3-18-g5258 From 860c6f203103f329d192547c4f62ff2471f99b43 Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Fri, 18 Feb 2011 10:41:29 -0500 Subject: Revert "Changes to optimized digitalWrte(), etc." This reverts commit aa1f1cbda9d6bb52785f98b40746920853d6579b. --- cores/arduino/wiring_digital.c | 76 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 4 deletions(-) (limited to 'cores/arduino/wiring_digital.c') diff --git a/cores/arduino/wiring_digital.c b/cores/arduino/wiring_digital.c index 9671045..95666b1 100755 --- a/cores/arduino/wiring_digital.c +++ b/cores/arduino/wiring_digital.c @@ -27,9 +27,28 @@ #include "wiring_private.h" #include "pins_arduino.h" -void pinMode_lookup(uint8_t pin, uint8_t val) +void pinMode_lookup(uint8_t pin, uint8_t mode) { - pinMode_implementation(pin, val); + uint8_t bit = digitalPinToBitMask(pin); + uint8_t port = digitalPinToPort(pin); + volatile uint8_t *reg; + + if (port == NOT_A_PIN) return; + + // JWS: can I let the optimizer do this? + reg = portModeRegister(port); + + if (mode == INPUT) { + uint8_t oldSREG = SREG; + cli(); + *reg &= ~bit; + SREG = oldSREG; + } else { + uint8_t oldSREG = SREG; + cli(); + *reg |= bit; + SREG = oldSREG; + } } // Forcing this inline keeps the callers from having to push their own stuff @@ -102,12 +121,61 @@ static void turnOffPWM(uint8_t timer) } } +void __digitalWriteOR_locked(volatile uint8_t*out, uint8_t bit) +{ + uint8_t oldSREG = SREG; + cli(); + *out |= bit; + SREG=oldSREG; +} + +void __digitalWriteAND_locked(volatile uint8_t*out, uint8_t bit) +{ + uint8_t oldSREG = SREG; + cli(); + *out &= bit; // NOTE - no inversion here, invert before calling!!! + SREG=oldSREG; +} + void digitalWrite_lookup(uint8_t pin, uint8_t val) { - digitalWrite_implementation(pin, val); + uint8_t timer = digitalPinToTimer(pin); + uint8_t bit = digitalPinToBitMask(pin); + uint8_t port = digitalPinToPort(pin); + volatile uint8_t *out; + + if (port == NOT_A_PIN) return; + + // If the pin that support PWM output, we need to turn it off + // before doing a digital write. + if (timer != NOT_ON_TIMER) turnOffPWM(timer); + + out = portOutputRegister(port); + + uint8_t oldSREG = SREG; + cli(); + + if (val == LOW) { + *out &= ~bit; + } else { + *out |= bit; + } + + SREG = oldSREG; } int digitalRead_lookup(uint8_t pin) { - digitalRead_implementation(pin); + uint8_t timer = digitalPinToTimer(pin); + uint8_t bit = digitalPinToBitMask(pin); + uint8_t port = digitalPinToPort(pin); + + if (port == NOT_A_PIN) return LOW; + + // If the pin that support PWM output, we need to turn it off + // before getting a digital reading. + if (timer != NOT_ON_TIMER) turnOffPWM(timer); + + if (*portInputRegister(port) & bit) return HIGH; + return LOW; } -- cgit v1.2.3-18-g5258 From 58d683239d80d4620a3ab35c4eac53bbe2c35d50 Mon Sep 17 00:00:00 2001 From: "David A. Mellis" Date: Thu, 3 Mar 2011 18:46:45 -0500 Subject: Removing optimized digitalWrite(), digitalRead(), pinMode(). --- cores/arduino/wiring_digital.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) (limited to 'cores/arduino/wiring_digital.c') diff --git a/cores/arduino/wiring_digital.c b/cores/arduino/wiring_digital.c index 95666b1..dd1b949 100755 --- a/cores/arduino/wiring_digital.c +++ b/cores/arduino/wiring_digital.c @@ -27,7 +27,7 @@ #include "wiring_private.h" #include "pins_arduino.h" -void pinMode_lookup(uint8_t pin, uint8_t mode) +void pinMode(uint8_t pin, uint8_t mode) { uint8_t bit = digitalPinToBitMask(pin); uint8_t port = digitalPinToPort(pin); @@ -121,23 +121,7 @@ static void turnOffPWM(uint8_t timer) } } -void __digitalWriteOR_locked(volatile uint8_t*out, uint8_t bit) -{ - uint8_t oldSREG = SREG; - cli(); - *out |= bit; - SREG=oldSREG; -} - -void __digitalWriteAND_locked(volatile uint8_t*out, uint8_t bit) -{ - uint8_t oldSREG = SREG; - cli(); - *out &= bit; // NOTE - no inversion here, invert before calling!!! - SREG=oldSREG; -} - -void digitalWrite_lookup(uint8_t pin, uint8_t val) +void digitalWrite(uint8_t pin, uint8_t val) { uint8_t timer = digitalPinToTimer(pin); uint8_t bit = digitalPinToBitMask(pin); @@ -164,7 +148,7 @@ void digitalWrite_lookup(uint8_t pin, uint8_t val) SREG = oldSREG; } -int digitalRead_lookup(uint8_t pin) +int digitalRead(uint8_t pin) { uint8_t timer = digitalPinToTimer(pin); uint8_t bit = digitalPinToBitMask(pin); -- cgit v1.2.3-18-g5258