[gnoduino: 2/237] Changes to optimized digitalWrte(), etc.
- From: Lucian Langa <lucilanga src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnoduino: 2/237] Changes to optimized digitalWrte(), etc.
- Date: Sat, 31 Mar 2012 20:14:59 +0000 (UTC)
commit eaa2c19de15230c729158656f680162815233163
Author: David A. Mellis <d mellis arduino cc>
Date: Fri Feb 11 19:29:46 2011 -0500
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.
arduino/cores/arduino/pins_arduino.h | 46 +---------
arduino/cores/arduino/wiring.h | 148 +++++++++++++++++++++++---------
arduino/cores/arduino/wiring_digital.c | 76 +---------------
3 files changed, 116 insertions(+), 154 deletions(-)
---
diff --git a/arduino/cores/arduino/pins_arduino.h b/arduino/cores/arduino/pins_arduino.h
index 63f4257..4bf6470 100644
--- a/arduino/cores/arduino/pins_arduino.h
+++ b/arduino/cores/arduino/pins_arduino.h
@@ -339,6 +339,8 @@ INLINED uint8_t inlined_digitalPinToBitMask(uint8_t pin)
}
}
+// XXX: this needs to return false (or -1) if the pin doesn't have a timer,
+// rather than throwing a compilation error.
INLINED uint8_t inlined_digitalPinToTimer(uint8_t pin)
{
switch(pin) {
@@ -453,6 +455,8 @@ INLINED uint8_t inlined_digitalPinToBitMask(uint8_t pin)
}
}
+// XXX: this needs to return false (or -1) if the pin doesn't have a timer,
+// rather than throwing a compilation error.
INLINED uint8_t inlined_digitalPinToTimer(uint8_t pin)
{
switch(pin) {
@@ -477,46 +481,4 @@ INLINED uint8_t inlined_digitalPinToTimer(uint8_t pin)
#define analogInPinToBit(P) (P)
-INLINED uint8_t digitalPinToPort(uint8_t pin) {
- if (__builtin_constant_p(pin))
- return inlined_digitalPinToPort(pin);
- else
- return pgm_read_byte( digital_pin_to_port_PGM + pin );
-}
-
-INLINED uint8_t digitalPinToBitMask(uint8_t pin) {
- if (__builtin_constant_p(pin))
- return inlined_digitalPinToBitMask(pin);
- else
- return pgm_read_byte( digital_pin_to_bit_mask_PGM + pin );
-}
-
-INLINED uint8_t digitalPinToTimer(uint8_t pin) {
- if (__builtin_constant_p(pin))
- return inlined_digitalPinToTimer(pin);
- else
- return pgm_read_byte( digital_pin_to_timer_PGM + pin );
-}
-
-INLINED volatile uint8_t *portOutputRegister(uint8_t index) {
- if (__builtin_constant_p(index))
- return inlined_portOutputRegister(index);
- else
- return (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + index ) );
-}
-
-INLINED volatile uint8_t* portInputRegister(uint8_t index) {
- if (__builtin_constant_p(index))
- return inlined_portInputRegister(index);
- else
- return (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + index) );
-}
-
-INLINED volatile uint8_t* portModeRegister(uint8_t index) {
- if (__builtin_constant_p(index))
- return inlined_portModeRegister(index);
- else
- return (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + index) );
-}
-
#endif
diff --git a/arduino/cores/arduino/wiring.h b/arduino/cores/arduino/wiring.h
index 433c87e..66ce2f7 100755
--- a/arduino/cores/arduino/wiring.h
+++ b/arduino/cores/arduino/wiring.h
@@ -130,68 +130,136 @@ void detachInterrupt(uint8_t);
void setup(void);
void loop(void);
+INLINED uint8_t digitalPinToPort(uint8_t pin) {
+ if (__builtin_constant_p(pin))
+ return inlined_digitalPinToPort(pin);
+ else
+ return pgm_read_byte( digital_pin_to_port_PGM + pin );
+}
+
+INLINED uint8_t digitalPinToBitMask(uint8_t pin) {
+ if (__builtin_constant_p(pin))
+ return inlined_digitalPinToBitMask(pin);
+ else
+ return pgm_read_byte( digital_pin_to_bit_mask_PGM + pin );
+}
+
+INLINED uint8_t digitalPinToTimer(uint8_t pin) {
+ if (__builtin_constant_p(pin))
+ return inlined_digitalPinToTimer(pin);
+ else
+ return pgm_read_byte( digital_pin_to_timer_PGM + pin );
+}
+
+INLINED volatile uint8_t *portOutputRegister(uint8_t index) {
+ if (__builtin_constant_p(index))
+ return inlined_portOutputRegister(index);
+ else
+ return (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + index ) );
+}
+
+INLINED volatile uint8_t* portInputRegister(uint8_t index) {
+ if (__builtin_constant_p(index))
+ return inlined_portInputRegister(index);
+ else
+ return (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + index) );
+}
+
+INLINED volatile uint8_t* portModeRegister(uint8_t index) {
+ if (__builtin_constant_p(index))
+ return inlined_portModeRegister(index);
+ else
+ return (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + index) );
+}
+
/*
* Check if a given pin requires locking.
* When accessing lower 32 IO ports we can use SBI/CBI instructions, which are atomic. However
* other IO ports require load+modify+store and we need to make them atomic by disabling
* interrupts.
*/
-INLINED int portWriteNeedsLocking(uint8_t pin)
+INLINED int registerWriteNeedsLocking(volatile uint8_t *reg)
{
/* SBI/CBI instructions only work on lower 32 IO ports */
- if (inlined_portOutputRegister(inlined_digitalPinToPort(pin)) > (volatile uint8_t*)&_SFR_IO8(0x1F)) {
+ if (reg > (volatile uint8_t*)&_SFR_IO8(0x1F)) {
return 1;
}
return 0;
}
-/*
- * These functions will perform OR/AND on a given register, and are atomic.
- */
-extern void __digitalWriteOR_locked(volatile uint8_t*out, uint8_t bit);
-extern void __digitalWriteAND_locked(volatile uint8_t*out, uint8_t bit);
-
+#define digitalWrite_implementation(pin, value)\
+do {\
+ uint8_t oldSREG;\
+ uint8_t bit = digitalPinToBitMask(pin);\
+ uint8_t port = digitalPinToPort(pin);\
+ volatile uint8_t *reg = portOutputRegister(port);\
+\
+ if (!__builtin_constant_p(pin) || registerWriteNeedsLocking(reg)) {\
+ oldSREG = SREG;\
+ cli();\
+ }\
+\
+ if (value == LOW) {\
+ *reg &= ~bit;\
+ } else {\
+ *reg |= bit;\
+ }\
+\
+ if (!__builtin_constant_p(pin) || registerWriteNeedsLocking(reg)) {\
+ SREG = oldSREG;\
+ }\
+} while(0)
+
INLINED void digitalWrite(uint8_t pin, uint8_t value)
{
- if (__builtin_constant_p(pin)) {
- if (portWriteNeedsLocking(pin)) {
- if (value==LOW) {
- __digitalWriteAND_locked(inlined_portOutputRegister(inlined_digitalPinToPort(pin)),~inlined_digitalPinToBitMask(pin));
- } else {
- __digitalWriteOR_locked(inlined_portOutputRegister(inlined_digitalPinToPort(pin)),inlined_digitalPinToBitMask(pin));
- }
- } else {
- if (value==LOW) {
- *inlined_portOutputRegister(inlined_digitalPinToPort(pin)) &= ~(inlined_digitalPinToBitMask(pin));
- } else {
- *inlined_portOutputRegister(inlined_digitalPinToPort(pin)) |= inlined_digitalPinToBitMask(pin);
- }
- }
- } else {
- digitalWrite_lookup(pin,value);
- }
+ if (__builtin_constant_p(pin)) digitalWrite_implementation(pin, value);
+ else digitalWrite_lookup(pin, value);
}
-INLINED void pinMode(uint8_t pin, uint8_t mode)
+#define pinMode_implementation(pin, value)\
+do {\
+ uint8_t bit = digitalPinToBitMask(pin);\
+ uint8_t oldSREG;\
+ uint8_t port = digitalPinToPort(pin);\
+ volatile uint8_t *reg = portModeRegister(port);\
+\
+ if (!__builtin_constant_p(pin) || registerWriteNeedsLocking(reg)) {\
+ oldSREG = SREG;\
+ cli();\
+ }\
+\
+ if (value == INPUT) { \
+ *reg &= ~bit;\
+ } else {\
+ *reg |= bit;\
+ }\
+\
+ if (!__builtin_constant_p(pin) || registerWriteNeedsLocking(reg)) {\
+ SREG = oldSREG;\
+ }\
+} while(0)
+
+INLINED void pinMode(uint8_t pin, uint8_t value)
{
- if (__builtin_constant_p(pin)) {
- if (mode==INPUT) {
- *inlined_portModeRegister(inlined_digitalPinToPort(pin)) &= ~(inlined_digitalPinToBitMask(pin));
- } else {
- *inlined_portModeRegister(inlined_digitalPinToPort(pin)) |= inlined_digitalPinToBitMask(pin);
- }
- } else {
- pinMode_lookup(pin,mode);
- }
+ if (__builtin_constant_p(pin)) pinMode_implementation(pin, value);
+ else pinMode_lookup(pin, value);
}
+#define digitalRead_implementation(pin)\
+do {\
+ uint8_t bit = digitalPinToBitMask(pin);\
+ uint8_t port = digitalPinToPort(pin);\
+\
+ if (port == NOT_A_PIN) return LOW;\
+\
+ if (*portInputRegister(port) & bit) return HIGH;\
+ return LOW;\
+} while(0)
+
INLINED int digitalRead(uint8_t pin)
{
- if (__builtin_constant_p(pin)) {
- return !! *inlined_portInputRegister(inlined_digitalPinToPort(pin));
- } else {
- return digitalRead_lookup(pin);
- }
+ if (__builtin_constant_p(pin)) digitalRead_implementation(pin);
+ else return digitalRead_lookup(pin);
}
diff --git a/arduino/cores/arduino/wiring_digital.c b/arduino/cores/arduino/wiring_digital.c
index 95666b1..9671045 100755
--- a/arduino/cores/arduino/wiring_digital.c
+++ b/arduino/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);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]