Adding digitalToggle to core?
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 35/100
- Issue type
- Feature
- Clarity
- Mostly clear
- Activity status
- Stale
- Tech stack
- cpp
- Domain
- embedded-iot
Research direction
Start by reading the proposed Arduino.h declaration and wiring_digital.c AVR implementation, then review ArduinoCore-API issue 77 and the linked Arduino issues and pull request. Done requires deciding the API shape, including the return value, and determining whether the proposal is suitable beyond the shown AVR implementation.
Written by the indexing model from the issue text.
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 pin
digitalWrite(pin, state);
state = 1 - state;
// read pin, invert and write back
digitalWrite(pin, !digitalRead(pin));
The latter one is slower as it redo a lot of "pin math", so I implemented a version of digitalToggle() for AVR.
Attached test sketch shows the gain compared to the two methods.
Results test on UNO
Time us 1000 calls
Reference: 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_t digitalToggle(uint8_t pin); // returns the new state of the pin
wiring_digital.c
uint8_t digitalToggle(uint8_t pin)
{
uint8_t port = digitalPinToPort(pin);
volatile uint8_t *out;
if (port == NOT_A_PIN) return 0;
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;
const uint8_t pin = 13;
uint8_t state = LOW;
void setup()
{
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);
}
void loop()
{
static int cnt = 0;
if (cnt == 60)
{
cnt = 0;
Serial.println();
}
cnt++;
// digitalToggle(pin);
int x = digitalToggle(pin);
Serial.print(x);
delay(1000);
}
Additional context
Additional requests
- https://github.com/arduino/ArduinoCore-API/issues/77#issue-494269676
- https://github.com/arduino/ArduinoCore-API/issues/77#issuecomment-287657867
- https://github.com/arduino/ArduinoCore-API/issues/77#issuecomment-287658811
- https://github.com/arduino/ArduinoCore-API/issues/77#issuecomment-287660708
- https://github.com/arduino/ArduinoCore-API/issues/77#issuecomment-287696536
- https://github.com/arduino/ArduinoCore-API/issues/77#issuecomment-287732174
- https://github.com/arduino/Arduino/pull/111
- https://github.com/arduino/Arduino/issues/11777
- Dominant language
- C++
- Stars
- 306
- Forks
- 150
- PR merge metrics
- No merged PRs in 30d
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from arduino/ArduinoCore-API
-
Difficulty 3/5 1-2 days Newbie friendliness 25/100
arduino/ArduinoCore-API#261 ·
-
bug
Difficulty 1/5 Under an hour Newbie friendliness 30/100
arduino/ArduinoCore-API#256 ·
-
enhancement
Difficulty 3/5 1-2 days Newbie friendliness 48/100
arduino/ArduinoCore-API#251 · 1 comment ·
-
enhancement
Difficulty 4/5 3-5 days Newbie friendliness 35/100
arduino/ArduinoCore-API#250 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 45/100
arduino/ArduinoCore-API#249 ·
All issues in arduino/ArduinoCore-API
Similar issues
-
Difficulty 1/5 Under an hour Newbie friendliness 90/100
AXERA-TECH/ax-llm#77 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 90/100
games-on-whales/wolf#509 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
-
bug-unconfirmed
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
NVIDIA/cuda-samples#453 ·