# GIGA R1 Wifi : Fast digital output handling

**URL:** <https://forum.arduino.cc/t/giga-r1-wifi-fast-digital-output-handling/1402729>\
**Category:** Programming\
**Created:** [August 17, 2025, 9:39am UTC](https://forum.arduino.cc/t/giga-r1-wifi-fast-digital-output-handling/1402729 "2025-08-17T09:39:30Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![denisfr67](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/denisfr67/32/1127134_2.png) [@denisfr67](https://forum.arduino.cc/u/denisfr67)\
**Post date:** [August 17, 2025, 9:39am UTC](https://forum.arduino.cc/t/giga-r1-wifi-fast-digital-output-handling/1402729/1 "2025-08-17T09:39:30Z")

</div>

Hi,  
I have discovered recently this forum and because I came here to solve a stupid bug and lost the time of nice people, I decided to show something that you could put in a 'tips & tricks' folder.

Question : how to manage on a Giga R1 the digital output ports in cases when time is critical ?

I have seen some complicated libraries, but let's try to keep simple things simple. Here we do NOT do multi threading.

Rem : **the code below has been improved** thanks to comments made by various users. It's the last version, those before having no interest for someone searching a solution. \*\*The test results are in [post #41](https://forum.arduino.cc/t/giga-r1-wifi-fast-digital-output-handling/1402729/41).

Idea : create a c++ class, and use it !

```arduino
class DigitalOutput
{
  public:
  GPIO_TypeDef *gpio;
  uint32_t setMask;
  uint32_t unsetMask;
  bool bInverted; // true -> High=0, Low=1
                            // false -> High=1, Low=0

  public:
                DigitalOutput()
                {
                  gpio = NULL;
                  setMask =
                  unsetMask = 0;
                  bInverted = false;
                }

// Initialisation with defined PIN name (as D2, LED_BUILTIN,...)
                void init(int _arduinoPin, bool _bInverted = false)
                {
                  uint32_t bit, portNum,pinName,portAddr;

                  // low 4 bits of "pinName" is the bit number
                  // upper bits of pinName are the port number (GPIOA = 0, GPIOB = 1, ...)
                  // These are evenly spaced in the memory map, so we can just offset from PORTA_BASE
                  pinName = digitalPinToPinName(_arduinoPin);
                  
                  bit = pinName & 0x0F; 
                  portNum = (pinName >> 4) & 0x0F;
                  portAddr = GPIOA_BASE + portNum * (GPIOB_BASE - GPIOA_BASE);

                  init((GPIO_TypeDef *)portAddr, bit, _bInverted);
                }

// Initialisation with GPIO / bit rank
  void init(GPIO_TypeDef *_gpio, uint32_t _bit, bool _bInverted = false)
                {
                  gpio = _gpio;

                  setMask = 1<<_bit; // BSRR 0..15
                  unsetMask = setMask<<16; // BSRR 16..31

                  bInverted = _bInverted;

                  // Set bit as digital output
                  // Rem : in MODER 2 bits configuration per bit
                  // 00 : input
                  // 01 : output
                  // 11 : analog
                  // 10 : alternate function mode (not used as i/o port)
                  gpio->MODER = (gpio->MODER & ~(0b11<<(_bit<<1))) | (0b01<<(_bit<<1));
                }

// Handles logical/electrical levels association 
  inline void setInverted(bool _bInverted) { bInverted = _bInverted; }

  inline bool isInverted() __attribute__ ((always_inline))
                { return bInverted; }

// Changes to logical Low
  inline void setLow() __attribute__ ((always_inline))
                { gpio->BSRR = (bInverted)? setMask : unsetMask; }

// Changes to logical High
  inline void setHigh() __attribute__ ((always_inline))
                { gpio->BSRR = (bInverted)? unsetMask : setMask; }

// Changes to logical level (false = logical Low, true = logical High)
  inline void setLevel(bool _bLevel) __attribute__ ((always_inline))
                { gpio->BSRR = (_bLevel ^ bInverted)? setMask : unsetMask; }

// Flips the output pin
  inline void flip() __attribute__ ((always_inline))
                { gpio->BSRR = (gpio->ODR & setMask)? unsetMask : setMask; }

// Gets the real value of output pin
  inline int getRealValue() __attribute__ ((always_inline))
                { return (gpio->ODR & setMask) ? HIGH : LOW; }
};

```

If you want to invert the behavior, you call **setInverted(bool)** to ask for it. If true, high and low states are 0/1 and not 1/0.

Example of use : the nice RGB LED.

If you check the documentation, the RGB leds are associated to PI12, PE3, PJ13.

It means GPIO I bit 12, GPIO E bit 3 and GPIO J bit 13.  
For them, the logic is inverted : 0 is HIGH in the sense that light is produced, 1 : LOW.

Now, the code :

```arduino
// Variables declaration

DigitalOutput led[3];

//
// Fonction qui fait clignoter une led
//

void Blink(DigitalOutput &_out, int _ms, int _nb=10)
{
  for (int i=0; i < _nb; i++)
  {
    _out.setHigh();
    delay(_ms);
    _out.setLow();
    delay(_ms);
  }
}

void setup()
{
// Each LED is declared and initialized as digital output (inverted)

  led[0].init(GPIOI ,12, true); // R
  led[1].init(GPIOJ ,13, true); // G
  led[2].init(GPIOE , 3, true); // B

// Each LED blinks 5 times 200ms

  for(int i = 0; i < 3;i++)
    Blink(led[i], 200,5);
}

```

Why is it interesting to do that way ?

Because during the execution everything is resolved in the Blink() function, nothing is called with stack handling and other complicated stuff.

Other example : stepper motor control.

At high speed, 3 motors with 1600 pulses (200 full steps at 1/8) for one complete rotation each, at 10 rotations/s you have 1600x3x10x2 (high/low) changes to do each second, **96000** outputs !

The M7 is the core dedicated to wifi and USB with the computer : high level control.

The M4 does the low level job, ie generates the pulses and the direction changes.  
At 240MHz, if you round 96000 to 100K, you have about 2400Hz/pulse, time for 5000 instructions.

If pulsing a motor takes a little bit time, the fact that at a moment you have to move several together can change the delay (d) between pulses :

[(motor 3)] - d - [(motor 3)] - d - [(motor 1)(motor 2)(motor 3)] - d - [(motor 3)] - ...

For motor 3, the delays are d, d + (motor 1&2 handling), d, ...

The execution has to be fast and smooth, the shorter the time used by each motor check, the less chance there is for a stall.

All optimisation of this code is welcome but, please, it should be kept human compatible !

---

<div class="post-metadata">

**Author:** ![J-M-L](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/j-m-l/32/766245_2.png) [@J-M-L](https://forum.arduino.cc/u/J-M-L)\
**Post date:** [August 17, 2025, 9:43am UTC](https://forum.arduino.cc/t/giga-r1-wifi-fast-digital-output-handling/1402729/2 "2025-08-17T09:43:54Z")

</div>

really tested?? 🙂

> [@denisfr67](#):
>
> ```arduino
> inline int GetValue() { return (gpio->ODR | mask) ? 1 : 0;}
> 
> ```

PS: arduino recommends camelCase

---

<div class="post-metadata">

**Author:** ![UKHeliBob](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/ukhelibob/32/215663_2.png) [@UKHeliBob](https://forum.arduino.cc/u/UKHeliBob)\
**Post date:** [August 17, 2025, 9:54am UTC](https://forum.arduino.cc/t/giga-r1-wifi-fast-digital-output-handling/1402729/3 "2025-08-17T09:54:51Z")

</div>

As your topic relates to an individual Arduino project and not the **Arduino Project** itself, which is the forum category that you posted in, it has been moved to a more relevant forum category

---

<div class="post-metadata">

**Author:** ![denisfr67](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/denisfr67/32/1127134_2.png) [@denisfr67](https://forum.arduino.cc/u/denisfr67)\
**Post date:** [August 17, 2025, 10:43am UTC](https://forum.arduino.cc/t/giga-r1-wifi-fast-digital-output-handling/1402729/4 "2025-08-17T10:43:48Z")

</div>

Not tested on this card. This function will be removed. Outputs are not inputs.

---

<div class="post-metadata">

**Author:** ![sonofcy](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/sonofcy/32/1283617_2.png) [@sonofcy](https://forum.arduino.cc/u/sonofcy)\
**Post date:** [August 17, 2025, 12:51pm UTC](https://forum.arduino.cc/t/giga-r1-wifi-fast-digital-output-handling/1402729/5 "2025-08-17T12:51:20Z")

</div>

If you think you have a better way to write code, that extraordinary claim requires extraordinary proof.  
Things like timing comparisons and assembly listings.

---

<div class="post-metadata">

**Author:** ![denisfr67](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/denisfr67/32/1127134_2.png) [@denisfr67](https://forum.arduino.cc/u/denisfr67)\
**Post date:** [August 17, 2025, 1:53pm UTC](https://forum.arduino.cc/t/giga-r1-wifi-fast-digital-output-handling/1402729/6 "2025-08-17T13:53:39Z")

</div>

When I write 'not tested on this card', it's a response to J-M-L about a removed method called GetValue().

For the rest, I have to admit I didn't go to the school of those who prefer calls to Java from Python launched in a shellscript loop. When I started computing, computers ran at 1MHz. The big IBMs ran at 16MHz (monsters!).

I'm counting on your extraordinary mix of logic and feminine intuition to understand that a simple assignment is faster than a heavy function call.

---

<div class="post-metadata">

**Author:** ![J-M-L](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/j-m-l/32/766245_2.png) [@J-M-L](https://forum.arduino.cc/u/J-M-L)\
**Post date:** [August 17, 2025, 1:55pm UTC](https://forum.arduino.cc/t/giga-r1-wifi-fast-digital-output-handling/1402729/7 "2025-08-17T13:55:49Z")

</div>

> [@denisfr67](#):
>
> When I write 'not tested on this card', it's a response to J-M-L about a removed method called GetValue().

My point was about the bug in the use of | instead of & in the function when you were applying the mask.

---

<div class="post-metadata">

**Author:** ![sonofcy](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/sonofcy/32/1283617_2.png) [@sonofcy](https://forum.arduino.cc/u/sonofcy)\
**Post date:** [August 17, 2025, 2:04pm UTC](https://forum.arduino.cc/t/giga-r1-wifi-fast-digital-output-handling/1402729/8 "2025-08-17T14:04:36Z")

</div>

When I started in 1959, we only had analog computers.  
I don't need a function to flip a bit, it's one line of code.  
My first language was machine code, then I got assembler, wow, what an improvement.  
Again, prove your work.

---

<div class="post-metadata">

**Author:** ![denisfr67](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/denisfr67/32/1127134_2.png) [@denisfr67](https://forum.arduino.cc/u/denisfr67)\
**Post date:** [August 17, 2025, 2:04pm UTC](https://forum.arduino.cc/t/giga-r1-wifi-fast-digital-output-handling/1402729/9 "2025-08-17T14:04:58Z")

</div>

You are right.

On DsPIC you cannot read an output digit, but on some specific cards, the device keeps trace of the last output (often used for functional tests).

I'll test the function with & mask and if it works I add it again.

PS: if you prefer 1, the '|' wasn't bad...

---

<div class="post-metadata">

**Author:** ![J-M-L](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/j-m-l/32/766245_2.png) [@J-M-L](https://forum.arduino.cc/u/J-M-L)\
**Post date:** [August 17, 2025, 2:08pm UTC](https://forum.arduino.cc/t/giga-r1-wifi-fast-digital-output-handling/1402729/10 "2025-08-17T14:08:06Z")

</div>

> [@denisfr67](#):
>
> PS: if you prefer 1, the '|' wasn't bad...

You would get 1 all the time indeed because the mask was not null. So you were getting a value but it had nothing to do with the pin status 🙂

---

<div class="post-metadata">

**Author:** ![denisfr67](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/denisfr67/32/1127134_2.png) [@denisfr67](https://forum.arduino.cc/u/denisfr67)\
**Post date:** [August 17, 2025, 2:22pm UTC](https://forum.arduino.cc/t/giga-r1-wifi-fast-digital-output-handling/1402729/11 "2025-08-17T14:22:11Z")

</div>

Your request is as strange as if you asked me to prove that the LEDs are actually blinking.

I have nothing to prove to you. I owe you nothing.  
Take example from J-M-L : nice and usefull comments.

---

<div class="post-metadata">

**Author:** ![sonofcy](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/sonofcy/32/1283617_2.png) [@sonofcy](https://forum.arduino.cc/u/sonofcy)\
**Post date:** [August 17, 2025, 2:36pm UTC](https://forum.arduino.cc/t/giga-r1-wifi-fast-digital-output-handling/1402729/12 "2025-08-17T14:36:06Z")

</div>

> [@denisfr67](#):
>
> how to manage the digital output ports in cases when time is critical ?

Your statement implies you can invert a bit faster. But even better, you imply the rest of us are using some sort of library to do that.

> [@denisfr67](#):
>
> I have seen some complicated libraries

---

<div class="post-metadata">

**Author:** ![denisfr67](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/denisfr67/32/1127134_2.png) [@denisfr67](https://forum.arduino.cc/u/denisfr67)\
**Post date:** [August 17, 2025, 2:49pm UTC](https://forum.arduino.cc/t/giga-r1-wifi-fast-digital-output-handling/1402729/13 "2025-08-17T14:49:55Z")

</div>

I checked the result (whith '&') and the register returns the last output really done.

The code is now complet in the first comment.

Thanks.

---

<div class="post-metadata">

**Author:** ![denisfr67](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/denisfr67/32/1127134_2.png) [@denisfr67](https://forum.arduino.cc/u/denisfr67)\
**Post date:** [August 17, 2025, 3:23pm UTC](https://forum.arduino.cc/t/giga-r1-wifi-fast-digital-output-handling/1402729/14 "2025-08-17T15:23:34Z")

</div>

Yes sir !

The usual way is :

1. pinMode(...,INPUT/OUTPUT/...)
2. digitalWrite(...,HIGH/LOW).

These functions are in libraries. It's a good and simple start to use things. But these functions are not efficient.

For testing, I decided to do 1000000 on/off, with digitalWrite() calls and then the same with setHigh()/setLow() :

```arduino
int ledRGB[]={D86,D87,D88};
DigitalOutput led[3];

void test()
{
  pinMode(ledRGB[0], OUTPUT);
  pinMode(ledRGB[1], OUTPUT);
  pinMode(ledRGB[2], OUTPUT);

  led[0].init(GPIOI,12,true);
  led[1].init(GPIOJ,13,true);
  led[2].init(GPIOE, 3,true);

  int t1,t2;
  int i;

  _println("test :");

  t1 = millis();
  for(i=0;i<1000000;i++)
  {
    digitalWrite(ledRGB[0], LOW);
    digitalWrite(ledRGB[0], HIGH);
  }
  t2 = millis();

  _println("delta1 = " + String(t2-t1));

  t1 = millis();
  for(i=0;i<1000000;i++)
  {
    led[0].setHigh();
    led[0].setLow();
  }
  t2 = millis();

  _println("delta2 = " + String(t2-t1));
}

```

The result is :

```arduino
test : 
delta1 = 636
delta2 = 171

```

3.4 times faster in non optimised code.

---

<div class="post-metadata">

**Author:** ![J-M-L](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/j-m-l/32/766245_2.png) [@J-M-L](https://forum.arduino.cc/u/J-M-L)\
**Post date:** [August 17, 2025, 3:34pm UTC](https://forum.arduino.cc/t/giga-r1-wifi-fast-digital-output-handling/1402729/15 "2025-08-17T15:34:13Z")

</div>

> [@denisfr67](#):
>
> The code is now complet in the first comment

another thing to consider if you have multiple instances

in `init` you sets the pin mode correctly

`gpio->MODER = (gpio->MODER & ~(0b11<<(_bit<<1))) | (0b01<<(_bit<<1));`

as this modifies only the two bits corresponding to the selected pin.

However, the `setHigh` and `setLow`methods modify the `ODR` register directly using `|=` or `&= ~mask`

➜ This is safe for a single pin, but if multiple `DigitalOutput` instances share the same GPIO port, and one instance modifies `ODR` without proper atomic operations or consideration of concurrency (e.g., interrupts also changing `ODR`), there is a risk that simultaneous writes could unintentionally change other pins' states. So it works fine in single-threaded, simple usage, but in more complex setups, you need to ensure that multiple instances on the same GPIO port do not interfere.

➜ Explore using the bit set/reset register (`BSRR`) instead of modifying `ODR` directly, which avoids accidentally changing other pins as on STM32, writing to `BSRR` atomically sets or resets a pin

something like

```arduino
inline void setLow() {
  if (gpio == nullptr) return;
  if (bInverted)
    gpio->BSRR = (mask << 16);
  else
    gpio->BSRR = mask;
}

inline void setHigh() {
  if (gpio == nullptr) return;
  if (bInverted)
    gpio->BSRR = mask;
  else
    gpio->BSRR = (mask << 16);
}

inline int getValue() {
  if (gpio == nullptr) return -1; // OR WHATEVER
  return (gpio->ODR & mask) ? 1 : 0;
}

```

---

<div class="post-metadata">

**Author:** ![sonofcy](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/sonofcy/32/1283617_2.png) [@sonofcy](https://forum.arduino.cc/u/sonofcy)\
**Post date:** [August 17, 2025, 3:37pm UTC](https://forum.arduino.cc/t/giga-r1-wifi-fast-digital-output-handling/1402729/16 "2025-08-17T15:37:28Z")

</div>

Sorry, I misunderstood your OP. I thought you were talking about some new way to invert a bit.  
As to your post 14 do you think a real system will notice the few microseconds it saved?  
You should know, I was twice awarded a commendation for saving $5 5Million to buy new computers because I made a small change in the code that was more efficient, but it was invoked 10s of millions of times a day.  
I made a similar small change in a customers code that their expert had been trying to find for 2 years.  
My point is these are examples of major costs and performance hits due to small coding errors. Your example of twiddling a pin mode doesn't get me excited. Have I misunderstood yet again?

---

<div class="post-metadata">

**Author:** ![jim-p](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/jim-p/32/922840_2.png) [@jim-p](https://forum.arduino.cc/u/jim-p)\
**Post date:** [August 17, 2025, 3:59pm UTC](https://forum.arduino.cc/t/giga-r1-wifi-fast-digital-output-handling/1402729/17 "2025-08-17T15:59:20Z")

</div>

Does this work on an Uno?  
What is GPIO\_TypeDef?

---

<div class="post-metadata">

**Author:** ![denisfr67](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/denisfr67/32/1127134_2.png) [@denisfr67](https://forum.arduino.cc/u/denisfr67)\
**Post date:** [August 17, 2025, 4:54pm UTC](https://forum.arduino.cc/t/giga-r1-wifi-fast-digital-output-handling/1402729/18 "2025-08-17T16:54:19Z")

</div>

Question 1 : I don't know. I use an Arduino GIGA R1.

Question 2 :

GPIO\_TypeDef is a structure mapped in the card memory at several places to control the GPIOs. It's a structure that respects exactly the specs described in the µ-proc documentation.

In the file stm32h747xx.h, for example, you find :

```arduino
/**
  * @brief General Purpose I/O
  */

typedef struct
{
  __IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */
  __IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */
  __IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */
  __IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */
  __IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */
  __IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */
  __IO uint32_t BSRR; /*!< GPIO port bit set/reset, Address offset: 0x18 */
  __IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */
  __IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */
} GPIO_TypeDef;

```

then memory addresses :

```arduino
...
#define PERIPH_BASE (0x40000000UL) /*!< Base address of : AHB/APB Peripherals */
...
#define D3_AHB1PERIPH_BASE (PERIPH_BASE + 0x18020000UL)
...
#define GPIOA_BASE (D3_AHB1PERIPH_BASE + 0x0000UL)
#define GPIOB_BASE (D3_AHB1PERIPH_BASE + 0x0400UL)
#define GPIOC_BASE (D3_AHB1PERIPH_BASE + 0x0800UL)
#define GPIOD_BASE (D3_AHB1PERIPH_BASE + 0x0C00UL)
#define GPIOE_BASE (D3_AHB1PERIPH_BASE + 0x1000UL)
#define GPIOF_BASE (D3_AHB1PERIPH_BASE + 0x1400UL)
#define GPIOG_BASE (D3_AHB1PERIPH_BASE + 0x1800UL)
#define GPIOH_BASE (D3_AHB1PERIPH_BASE + 0x1C00UL)
#define GPIOI_BASE (D3_AHB1PERIPH_BASE + 0x2000UL)
#define GPIOJ_BASE (D3_AHB1PERIPH_BASE + 0x2400UL)
#define GPIOK_BASE (D3_AHB1PERIPH_BASE + 0x2800UL)

```

On which the usable structures are mapped :

```arduino
#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE)
#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)
#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE)
#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE)
#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE)
#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE)
#define GPIOH ((GPIO_TypeDef *) GPIOH_BASE)
#define GPIOI ((GPIO_TypeDef *) GPIOI_BASE)
#define GPIOJ ((GPIO_TypeDef *) GPIOJ_BASE)
#define GPIOK ((GPIO_TypeDef *) GPIOK_BASE)

```

Check if you find the same stuff for your platform.

---

<div class="post-metadata">

**Author:** ![jim-p](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/jim-p/32/922840_2.png) [@jim-p](https://forum.arduino.cc/u/jim-p)\
**Post date:** [August 17, 2025, 4:59pm UTC](https://forum.arduino.cc/t/giga-r1-wifi-fast-digital-output-handling/1402729/19 "2025-08-17T16:59:27Z")

</div>

No such thing for an Uno.

So your class, as is, is only usable with a GIGA?

---

<div class="post-metadata">

**Author:** ![J-M-L](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/j-m-l/32/766245_2.png) [@J-M-L](https://forum.arduino.cc/u/J-M-L)\
**Post date:** [August 17, 2025, 5:13pm UTC](https://forum.arduino.cc/t/giga-r1-wifi-fast-digital-output-handling/1402729/20 "2025-08-17T17:13:02Z")

</div>

It directly manipulates the STM32 GPIO registers to configure pins and set their output states, bypassing the Arduino `digitalWrite` abstraction. It is not applicable to AVR-based Arduinos, nor to ESP32

[Next page](https://forum.arduino.cc/t/giga-r1-wifi-fast-digital-output-handling/1402729.md?page=2)
