Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork130
Open
Labels
Description
Description
The Arduino core has a digitalWrite() and a digitalRead() function.
In many sketches there is a need to toggle a pin, either for a blinking LED or a clock pin for swSPI etc.
There are two typical ways to invert a pin - see code below
// using a state holding the value of the pindigitalWrite(pin, state); state =1 - state;// read pin, invert and write backdigitalWrite(pin, !digitalRead(pin));
The latter one is slower as it redo a lot of "pin math", so I implemented a version ofdigitalToggle() for AVR.
Attached test sketch shows the gain compared to the two methods.
Results test on UNO
Time us1000 callsReference:7392// read invert write Var:4784// use state var Toggle:3964// use digitalToggle returning state Toggle:3520// use digitalToggle returning NO state
The gain of toggle returning state is 46% resp 16%
The gain of toggle returning NO state is 52% resp 26%
Imho these gains are interesting, esp for clocking data
Implementation for AVR
Arduino.h
uint8_tdigitalToggle(uint8_t pin);// returns the new state of the pin
wiring_digital.c
uint8_tdigitalToggle(uint8_t pin){uint8_t port =digitalPinToPort(pin);volatileuint8_t *out;if (port == NOT_A_PIN)return0;uint8_t timer =digitalPinToTimer(pin);if (timer != NOT_ON_TIMER)turnOffPWM(timer);uint8_t bit =digitalPinToBitMask(pin); out =portOutputRegister(port);uint8_t oldSREG = SREG;cli(); *out ^= bit;// invert bit SREG = oldSREG;return ((*out & bit) !=0);}
Note: a no state returning version is straightforward given the above code.
Test sketch
uint32_t start, Tref, Tref2, Tnew;constuint8_t pin =13;uint8_t state = LOW;voidsetup(){ Serial.begin(115200); Serial.println(); Serial.println(__FILE__);pinMode(pin, OUTPUT);digitalWrite(pin, LOW); start =micros();for (int i =0; i <1000; i++)digitalWrite(pin, !digitalRead(pin)); Tref =micros() - start; start =micros();for (int i =0; i <1000; i++) {digitalWrite(pin, state); state =1 - state; } Tref2 =micros() - start; start =micros();for (int i =0; i <1000; i++)digitalToggle(pin); Tnew =micros() - start; Serial.print("Reference:\t"); Serial.println(Tref); Serial.print(" Var:\t"); Serial.println(Tref2); Serial.print(" Toggle:\t"); Serial.println(Tnew); Serial.print(" Gain:\t"); Serial.println(Tref - Tnew); Serial.print(" Perc:\t"); Serial.println(100.0 - (100.0 * Tnew) / Tref,1);pinMode(13, OUTPUT);}voidloop(){staticint cnt =0;if (cnt ==60) { cnt =0; Serial.println(); } cnt++;// digitalToggle(pin);int x =digitalToggle(pin); Serial.print(x);delay(1000);}