[gnoduino: 1/237] Optimized digitalWrite(), etc. from Alvaro Lopez.



commit 51534263c4cd5956ebae567fa28e98e762d44797
Author: David A. Mellis <d mellis arduino cc>
Date:   Fri Feb 11 17:53:24 2011 -0500

    Optimized digitalWrite(), etc. from Alvaro Lopez.

 arduino/cores/arduino/pins_arduino.h   |  452 +++++++++++++++++++++++++++++++-
 arduino/cores/arduino/wiring.h         |   73 +++++-
 arduino/cores/arduino/wiring_digital.c |   33 ++-
 3 files changed, 537 insertions(+), 21 deletions(-)
---
diff --git a/arduino/cores/arduino/pins_arduino.h b/arduino/cores/arduino/pins_arduino.h
index bc931c5..63f4257 100644
--- a/arduino/cores/arduino/pins_arduino.h
+++ b/arduino/cores/arduino/pins_arduino.h
@@ -49,6 +49,10 @@
 #define TIMER5B 15
 #define TIMER5C 16
 
+#ifndef INLINED
+#define INLINED static __attribute__((always_inline)) inline
+#endif
+
 #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
 const static uint8_t SS   = 53;
 const static uint8_t MOSI = 51;
@@ -72,17 +76,447 @@ extern const uint8_t PROGMEM digital_pin_to_port_PGM[];
 extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[];
 extern const uint8_t PROGMEM digital_pin_to_timer_PGM[];
 
+// inlined versions of lookup-table-based pin mappings. Don't use directly.
+
+// Don't use PA, so on, might clash with sketch
+
+#define PORT_INDEX_PA 1
+#define PORT_INDEX_PB 2
+#define PORT_INDEX_PC 3
+#define PORT_INDEX_PD 4
+#define PORT_INDEX_PE 5
+#define PORT_INDEX_PF 6
+#define PORT_INDEX_PG 7
+#define PORT_INDEX_PH 8
+#define PORT_INDEX_PJ 10
+#define PORT_INDEX_PK 11
+#define PORT_INDEX_PL 12
+
+__attribute__((error("Invalid pin specified. This pin does not map to any I/O port"))) static void invalidPinSpecified(void);
+
+
+#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
+
+INLINED volatile uint8_t *inlined_portModeRegister(uint8_t port_index)
+{
+	switch (port_index) {
+	case 1: return &DDRA;
+	case 2: return &DDRB;
+	case 3: return &DDRC;
+	case 4: return &DDRD;
+	case 5: return &DDRE;
+	case 6: return &DDRF;
+	case 7: return &DDRG;
+	case 8: return &DDRH;
+	case 10: return &DDRJ;
+	case 11: return &DDRK;
+	case 12: return &DDRL;
+	default: return NOT_A_PORT;
+	}
+}
+
+INLINED volatile uint8_t *inlined_portOutputRegister(uint8_t port_index)
+{
+	switch (port_index) {
+	case 1: return &PORTA;
+	case 2: return &PORTB;
+	case 3: return &PORTC;
+	case 4: return &PORTD;
+	case 5: return &PORTE;
+	case 6: return &PORTF;
+	case 7: return &PORTG;
+	case 8: return &PORTH;
+	case 10: return &PORTJ;
+	case 11: return &PORTK;
+	case 12: return &PORTL;
+	default: return NOT_A_PORT;
+	}
+}
+
+INLINED volatile uint8_t *inlined_portInputRegister(uint8_t port_index)
+{
+	switch (port_index) {
+	case 1: return &PINA;
+	case 2: return &PINB;
+	case 3: return &PINC;
+	case 4: return &PIND;
+	case 5: return &PINE;
+	case 6: return &PINF;
+	case 7: return &PING;
+	case 8: return &PINH;
+	case 10: return &PINJ;
+	case 11: return &PINK;
+	case 12: return &PINL;
+	default: return NOT_A_PIN;
+	}
+};
+
+INLINED uint8_t inlined_digitalPinToPort(uint8_t pin)
+{
+	switch (pin) {
+	case 0:  // PE 0 ** 0 ** USART0_RX
+	case 1:  // PE 1 ** 1 ** USART0_TX
+	case 2:  // PE 4 ** 2 ** PWM2
+	case 3:  // PE 5 ** 3 ** PWM3
+		return PORT_INDEX_PE;
+
+	case 4:  // PG 5 ** 4 ** PWM4
+		return PORT_INDEX_PG;
+
+	case 5:  // PE 3 ** 5 ** PWM5
+		return PORT_INDEX_PE;
+
+	case 6:  // PH 3 ** 6 ** PWM6
+	case 7:  // PH 4 ** 7 ** PWM7
+	case 8:  // PH 5 ** 8 ** PWM8
+	case 9:  // PH 6 ** 9 ** PWM9
+		return PORT_INDEX_PH;
+
+	case 10: // PB 4 ** 10 ** PWM10
+	case 11: // PB 5 ** 11 ** PWM11
+	case 12: // PB 6 ** 12 ** PWM12
+	case 13: // PB 7 ** 13 ** PWM13
+		return PORT_INDEX_PB;
+
+	case 14: // PJ 1 ** 14 ** USART3_TX
+	case 15: // PJ 0 ** 15 ** USART3_RX
+		return PORT_INDEX_PJ;
+
+	case 16: // PH 1 ** 16 ** USART2_TX
+	case 17: // PH 0 ** 17 ** USART2_RX
+		return PORT_INDEX_PH;
+
+	case 18: // PD 3 ** 18 ** USART1_TX
+	case 19: // PD 2 ** 19 ** USART1_RX
+	case 20: // PD 1 ** 20 ** I2C_SDA
+	case 21: // PD 0 ** 21 ** I2C_SCL
+		return PORT_INDEX_PD;
+
+	case 22: // PA 0 ** 22 ** D22
+	case 23: // PA 1 ** 23 ** D23
+	case 24: // PA 2 ** 24 ** D24
+	case 25: // PA 3 ** 25 ** D25
+	case 26: // PA 4 ** 26 ** D26
+	case 27: // PA 5 ** 27 ** D27
+	case 28: // PA 6 ** 28 ** D28
+	case 29: // PA 7 ** 29 ** D29
+		return PORT_INDEX_PA;
+
+	case 30: // PC 7 ** 30 ** D30
+	case 31: // PC 6 ** 31 ** D31
+	case 32: // PC 5 ** 32 ** D32
+	case 33: // PC 4 ** 33 ** D33
+	case 34: // PC 3 ** 34 ** D34
+	case 35: // PC 2 ** 35 ** D35
+	case 36: // PC 1 ** 36 ** D36
+	case 37: // PC 0 ** 37 ** D37
+		return PORT_INDEX_PC;
+
+	case 38: // PD 7 ** 38 ** D38
+		return PORT_INDEX_PD;
+
+	case 39: // PG 2 ** 39 ** D39
+	case 40: // PG 1 ** 40 ** D40
+	case 41: // PG 0 ** 41 ** D41
+		return PORT_INDEX_PG;
+
+	case 42: // PL 7 ** 42 ** D42
+	case 43: // PL 6 ** 43 ** D43
+	case 44: // PL 5 ** 44 ** D44
+	case 45: // PL 4 ** 45 ** D45
+	case 46: // PL 3 ** 46 ** D46
+	case 47: // PL 2 ** 47 ** D47
+	case 48: // PL 1 ** 48 ** D48
+	case 49: // PL 0 ** 49 ** D49
+		return PORT_INDEX_PL;
+
+	case 50: // PB 3 ** 50 ** SPI_MISO
+	case 51: // PB 2 ** 51 ** SPI_MOSI
+	case 52: // PB 1 ** 52 ** SPI_SCK
+	case 53: // PB 0 ** 53 ** SPI_SS
+		return PORT_INDEX_PB;
+
+	case 54: // PF 0 ** 54 ** A0
+	case 55: // PF 1 ** 55 ** A1
+	case 56: // PF 2 ** 56 ** A2
+	case 57: // PF 3 ** 57 ** A3
+	case 58: // PF 4 ** 58 ** A4
+	case 59: // PF 5 ** 59 ** A5
+	case 60: // PF 6 ** 60 ** A6
+	case 61: // PF 7 ** 61 ** A7
+		return PORT_INDEX_PF;
+
+	case 62: // PK 0 ** 62 ** A8
+	case 63: // PK 1 ** 63 ** A9
+	case 64: // PK 2 ** 64 ** A10
+	case 65: // PK 3 ** 65 ** A11
+	case 66: // PK 4 ** 66 ** A12
+	case 67: // PK 5 ** 67 ** A13
+	case 68: // PK 6 ** 68 ** A14
+	case 69: // PK 7 ** 69 ** A15
+		return PORT_INDEX_PK;
+	default:
+		invalidPinSpecified();
+	}
+}
+
+INLINED uint8_t inlined_digitalPinToBitMask(uint8_t pin)
+{
+	switch(pin) {
+	case  0: return _BV( 0 ); // PE 0 ** 0 ** USART0_RX
+	case  1: return _BV( 1 ); // PE 1 ** 1 ** USART0_TX
+	case  2: return _BV( 4 ); // PE 4 ** 2 ** PWM2
+	case  3: return _BV( 5 ); // PE 5 ** 3 ** PWM3
+	case  4: return _BV( 5 ); // PG 5 ** 4 ** PWM4
+	case  5: return _BV( 3 ); // PE 3 ** 5 ** PWM5
+	case  6: return _BV( 3 ); // PH 3 ** 6 ** PWM6
+	case  7: return _BV( 4 ); // PH 4 ** 7 ** PWM7
+	case  8: return _BV( 5 ); // PH 5 ** 8 ** PWM8
+	case  9: return _BV( 6 ); // PH 6 ** 9 ** PWM9
+	case 10: return _BV( 4 ); // PB 4 ** 10 ** PWM10
+	case 11: return _BV( 5 ); // PB 5 ** 11 ** PWM11
+	case 12: return _BV( 6 ); // PB 6 ** 12 ** PWM12
+	case 13: return _BV( 7 ); // PB 7 ** 13 ** PWM13
+	case 14: return _BV( 1 ); // PJ 1 ** 14 ** USART3_TX
+	case 15: return _BV( 0 ); // PJ 0 ** 15 ** USART3_RX
+	case 16: return _BV( 1 ); // PH 1 ** 16 ** USART2_TX
+	case 17: return _BV( 0 ); // PH 0 ** 17 ** USART2_RX
+	case 18: return _BV( 3 ); // PD 3 ** 18 ** USART1_TX
+	case 19: return _BV( 2 ); // PD 2 ** 19 ** USART1_RX
+	case 20: return _BV( 1 ); // PD 1 ** 20 ** I2C_SDA
+	case 21: return _BV( 0 ); // PD 0 ** 21 ** I2C_SCL
+	case 22: return _BV( 0 ); // PA 0 ** 22 ** D22
+	case 23: return _BV( 1 ); // PA 1 ** 23 ** D23
+	case 24: return _BV( 2 ); // PA 2 ** 24 ** D24
+	case 25: return _BV( 3 ); // PA 3 ** 25 ** D25
+	case 26: return _BV( 4 ); // PA 4 ** 26 ** D26
+	case 27: return _BV( 5 ); // PA 5 ** 27 ** D27
+	case 28: return _BV( 6 ); // PA 6 ** 28 ** D28
+	case 29: return _BV( 7 ); // PA 7 ** 29 ** D29
+	case 30: return _BV( 7 ); // PC 7 ** 30 ** D30
+	case 31: return _BV( 6 ); // PC 6 ** 31 ** D31
+	case 32: return _BV( 5 ); // PC 5 ** 32 ** D32
+	case 33: return _BV( 4 ); // PC 4 ** 33 ** D33
+	case 34: return _BV( 3 ); // PC 3 ** 34 ** D34
+	case 35: return _BV( 2 ); // PC 2 ** 35 ** D35
+	case 36: return _BV( 1 ); // PC 1 ** 36 ** D36
+	case 37: return _BV( 0 ); // PC 0 ** 37 ** D37
+	case 38: return _BV( 7 ); // PD 7 ** 38 ** D38
+	case 39: return _BV( 2 ); // PG 2 ** 39 ** D39
+	case 40: return _BV( 1 ); // PG 1 ** 40 ** D40
+	case 41: return _BV( 0 ); // PG 0 ** 41 ** D41
+	case 42: return _BV( 7 ); // PL 7 ** 42 ** D42
+	case 43: return _BV( 6 ); // PL 6 ** 43 ** D43
+	case 44: return _BV( 5 ); // PL 5 ** 44 ** D44
+	case 45: return _BV( 4 ); // PL 4 ** 45 ** D45
+	case 46: return _BV( 3 ); // PL 3 ** 46 ** D46
+	case 47: return _BV( 2 ); // PL 2 ** 47 ** D47
+	case 48: return _BV( 1 ); // PL 1 ** 48 ** D48
+	case 49: return _BV( 0 ); // PL 0 ** 49 ** D49
+	case 50: return _BV( 3 ); // PB 3 ** 50 ** SPI_MISO
+	case 51: return _BV( 2 ); // PB 2 ** 51 ** SPI_MOSI
+	case 52: return _BV( 1 ); // PB 1 ** 52 ** SPI_SCK
+	case 53: return _BV( 0 ); // PB 0 ** 53 ** SPI_SS
+	case 54: return _BV( 0 ); // PF 0 ** 54 ** A0
+	case 55: return _BV( 1 ); // PF 1 ** 55 ** A1
+	case 56: return _BV( 2 ); // PF 2 ** 56 ** A2
+	case 57: return _BV( 3 ); // PF 3 ** 57 ** A3
+	case 58: return _BV( 4 ); // PF 4 ** 58 ** A4
+	case 59: return _BV( 5 ); // PF 5 ** 59 ** A5
+	case 60: return _BV( 6 ); // PF 6 ** 60 ** A6
+	case 61: return _BV( 7 ); // PF 7 ** 61 ** A7
+	case 62: return _BV( 0 ); // PK 0 ** 62 ** A8
+	case 63: return _BV( 1 ); // PK 1 ** 63 ** A9
+	case 64: return _BV( 2 ); // PK 2 ** 64 ** A10
+	case 65: return _BV( 3 ); // PK 3 ** 65 ** A11
+	case 66: return _BV( 4 ); // PK 4 ** 66 ** A12
+	case 67: return _BV( 5 ); // PK 5 ** 67 ** A13
+	case 68: return _BV( 6 ); // PK 6 ** 68 ** A14
+	case 69: return _BV( 7 ); // PK 7 ** 69 ** A15
+	default:
+		// TODO: add error here
+		invalidPinSpecified();
+	}
+}
+
+INLINED uint8_t inlined_digitalPinToTimer(uint8_t pin)
+{
+	switch(pin) {
+	case  2: return TIMER3B; // PE 4 ** 2 ** PWM2
+	case  3: return TIMER3C; // PE 5 ** 3 ** PWM3
+	case  4: return TIMER0B; // PG 5 ** 4 ** PWM4
+	case  5: return TIMER3A; // PE 3 ** 5 ** PWM5
+	case  6: return TIMER4A; // PH 3 ** 6 ** PWM6
+	case  7: return TIMER4B; // PH 4 ** 7 ** PWM7
+	case  8: return TIMER4C; // PH 5 ** 8 ** PWM8
+	case  9: return TIMER2B; // PH 6 ** 9 ** PWM9
+	case 10: return TIMER2A; // PB 4 ** 10 ** PWM10
+	case 11: return TIMER1A; // PB 5 ** 11 ** PWM11
+	case 12: return TIMER1B; // PB 6 ** 12 ** PWM12
+	case 13: return TIMER0A; // PB 7 ** 13 ** PWM13
+	case 44: return TIMER5C; // PL 5 ** 44 ** D44
+	case 45: return TIMER5B; // PL 4 ** 45 ** D45
+	case 46: return TIMER5A; // PL 3 ** 46 ** D46
+	default: invalidPinSpecified();
+	}
+}
+
+#else // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
+
+INLINED volatile uint8_t *inlined_portModeRegister(uint8_t port_index)
+{
+	switch (port_index) {
+	case 2: return &DDRB;
+	case 3: return &DDRC;
+	case 4: return &DDRD;
+	default: invalidPinSpecified();
+	}
+}
+
+INLINED volatile uint8_t *inlined_portOutputRegister(uint8_t port_index)
+{
+	switch (port_index) {
+	case 2: return &PORTB;
+	case 3: return &PORTC;
+	case 4: return &PORTD;
+	default: invalidPinSpecified();
+	}
+}
+
+INLINED volatile uint8_t *inlined_portInputRegister(uint8_t port_index)
+{
+	switch (port_index) {
+	case 2: return &PINB;
+	case 3: return &PINC;
+	case 4: return &PIND;
+	default: invalidPinSpecified();
+	}
+}
+
+INLINED uint8_t inlined_digitalPinToPort(uint8_t pin)
+{
+	switch(pin) {
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+		return PORT_INDEX_PD;
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+	case 13:
+		return PORT_INDEX_PB;
+	case 14:
+	case 15:
+	case 16:
+	case 17:
+	case 18:
+	case 19:
+		return PORT_INDEX_PC;
+	default:
+		invalidPinSpecified();
+	}
+}
+
+INLINED uint8_t inlined_digitalPinToBitMask(uint8_t pin)
+{
+	switch(pin) {
+	case 0: return _BV(0); /* 0, port D */
+	case 1: return _BV(1);
+	case 2: return _BV(2);
+	case 3: return _BV(3);
+	case 4: return _BV(4);
+	case 5: return _BV(5);
+	case 6: return _BV(6);
+	case 7: return _BV(7);
+	case 8: return _BV(0); /* 8, port B */
+	case 9: return _BV(1);
+	case 10: return _BV(2);
+	case 11: return _BV(3);
+	case 12: return _BV(4);
+	case 13: return _BV(5);
+	case 14: return _BV(0); /* 14, port C */
+	case 15: return _BV(1);
+	case 16: return _BV(2);
+	case 17: return _BV(3);
+	case 18: return _BV(4);
+	case 19: return _BV(5);
+	default:
+		// TODO: throw error here
+		invalidPinSpecified();
+	}
+}
+
+INLINED uint8_t inlined_digitalPinToTimer(uint8_t pin)
+{
+	switch(pin) {
+#if defined(__AVR_ATmega8__)
+	case 11: return TIMER2;
+#else
+	case  3: return TIMER2B;
+	case  5: return TIMER0B;
+	case  6: return TIMER0A;
+	case 11: return TIMER2A;
+#endif
+	case  9: return TIMER1A;
+	case 10: return TIMER1B;
+	default: invalidPinSpecified();
+	}
+}
+
+#endif // defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
+
 // Get the bit location within the hardware port of the given virtual pin.
 // This comes from the pins_*.c file for the active board configuration.
-// 
-// These perform slightly better as macros compared to inline functions
-//
-#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) )
-#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) )
-#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) )
+
 #define analogInPinToBit(P) (P)
-#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) )
-#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) )
-#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (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 e29959b..433c87e 100755
--- a/arduino/cores/arduino/wiring.h
+++ b/arduino/cores/arduino/wiring.h
@@ -26,8 +26,10 @@
 #define Wiring_h
 
 #include <avr/io.h>
+#include <avr/interrupt.h>
 #include <stdlib.h>
 #include "binary.h"
+#include "pins_arduino.h"
 
 #ifdef __cplusplus
 extern "C"{
@@ -106,9 +108,9 @@ typedef uint8_t byte;
 
 void init(void);
 
-void pinMode(uint8_t, uint8_t);
-void digitalWrite(uint8_t, uint8_t);
-int digitalRead(uint8_t);
+void pinMode_lookup(uint8_t, uint8_t);
+void digitalWrite_lookup(uint8_t, uint8_t);
+int digitalRead_lookup(uint8_t);
 int analogRead(uint8_t);
 void analogReference(uint8_t mode);
 void analogWrite(uint8_t, int);
@@ -128,6 +130,71 @@ void detachInterrupt(uint8_t);
 void setup(void);
 void loop(void);
 
+/*
+ * 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)
+{
+	/* SBI/CBI instructions only work on lower 32 IO ports */
+	if (inlined_portOutputRegister(inlined_digitalPinToPort(pin)) > (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);
+
+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);
+	}
+}
+
+INLINED void pinMode(uint8_t pin, uint8_t mode)
+{
+	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);
+	}
+}
+
+INLINED int digitalRead(uint8_t pin)
+{
+	if (__builtin_constant_p(pin)) {
+		return !! *inlined_portInputRegister(inlined_digitalPinToPort(pin));
+	} else {
+		return digitalRead_lookup(pin);
+	}
+}
+
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
diff --git a/arduino/cores/arduino/wiring_digital.c b/arduino/cores/arduino/wiring_digital.c
index 0949da4..95666b1 100755
--- a/arduino/cores/arduino/wiring_digital.c
+++ b/arduino/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);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]