arduino / arduino/ArduinoCore-API

Adding digitalToggle to core?

Open
#130 6 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
C++
Stars
306
Forks
150
PR merge metrics
No merged PRs in 30d

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
```cpp
// 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**
```cpp
uint8_t digitalToggle(uint8_t pin); // returns the new state of the pin
```

**wiring_digital.c**
```cpp
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

[digitalToggle.zip](https://github.com/arduino/Arduino/files/5646909/digitalToggle.zip)

```cpp
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

Contributor guide

No contributing guide indexed for this repository

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.

Assessment

Tech stack
cpp
Domain
embedded-iot
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.