diff --git a/cores/rp2040/Arduino.h b/cores/rp2040/Arduino.h index 515caf7f4..6bb22260f 100644 --- a/cores/rp2040/Arduino.h +++ b/cores/rp2040/Arduino.h @@ -105,6 +105,9 @@ void analogWriteFreq(uint32_t freq); void analogWriteRange(uint32_t range); void analogWriteResolution(int res); +// GPIO RP2040-specific calls +void setPinInvert(pin_size_t ulPin, bool invert); + #ifdef __cplusplus } // extern "C" #endif diff --git a/cores/rp2040/wiring_digital.cpp b/cores/rp2040/wiring_digital.cpp index a5b300e8b..cceef4e57 100644 --- a/cores/rp2040/wiring_digital.cpp +++ b/cores/rp2040/wiring_digital.cpp @@ -25,13 +25,27 @@ extern void __clearADCPin(pin_size_t p); static PinMode _pm[__GPIOCNT]; +extern "C" void setPinInvert(pin_size_t ulPin, bool invert) __attribute__((weak, alias("__setPinInvert"))); +extern "C" void __setPinInvert(pin_size_t ulPin, bool invert) { + if (ulPin >= __GPIOCNT) { + DEBUGCORE("ERROR: Illegal pin in setPinInvert (%d)\n", ulPin); + return; + } + + if (invert) + gpio_set_outover(ulPin, GPIO_OVERRIDE_INVERT); + else + gpio_set_outover(ulPin, GPIO_OVERRIDE_NORMAL); +} + extern "C" void pinMode(pin_size_t ulPin, PinMode ulMode) __attribute__((weak, alias("__pinMode"))); extern "C" void __pinMode(pin_size_t ulPin, PinMode ulMode) { if (ulPin >= __GPIOCNT) { DEBUGCORE("ERROR: Illegal pin in pinMode (%d)\n", ulPin); return; } - + + gpio_set_function(ulPin, GPIO_FUNC_SIO); switch (ulMode) { case INPUT: gpio_init(ulPin); @@ -90,7 +104,6 @@ extern "C" void __digitalWrite(pin_size_t ulPin, PinStatus ulVal) { DEBUGCORE("ERROR: Illegal pin in pinMode (%d)\n", ulPin); return; } - gpio_set_function(ulPin, GPIO_FUNC_SIO); if (_pm[ulPin] == INPUT_PULLDOWN) { if (ulVal == LOW) { gpio_set_dir(ulPin, false); diff --git a/docs/digital.rst b/docs/digital.rst index c665c7386..c3e1b935c 100644 --- a/docs/digital.rst +++ b/docs/digital.rst @@ -18,6 +18,34 @@ Output Modes (Pad Strength) --------------------------- The Raspberry Pi Pico has the ability to set the current that a pin (actually the pad associated with it) is capable of supplying. The current can be set to values of 2mA, 4mA, 8mA and 12mA. By default, on a reset, the setting is 4mA. A `pinMode(x, OUTPUT)`, where `x` is the pin number, is also the default setting. 4 settings have been added for use with `pinMode`: `OUTPUT_2MA`, `OUTPUT_4MA`, which has the same behavior as `OUTPUT`, `OUTPUT_8MA` and `OUTPUT_12MA`. +GPIO Output Inversion +--------------------- +The RP2040 and RP2350 microcontrollers support configurable output inversion on all GPIO pins. +This feature allows each GPIO to output either the logical value or its inverted equivalent, +without requiring changes to the underlying logic of your application. + +This is especially useful when adapting existing libraries or hardware that use opposite logic levels. +By configuring inversion at the GPIO level, you can achieve compatibility without rewriting code. + +Function +-------- + +.. code-block:: c + + void setPinInvert(uint pin, bool invert); + +**Parameters:** + +- ``pin``: The GPIO number to configure. +- ``invert``: + + - ``true`` — Enables output inversion (logical 1 becomes 0, and vice versa). + - ``false`` — Disables inversion, restoring default non-inverted output. + +.. note:: + + All GPIO pins are configured as non-inverting outputs by default. + Tone/noTone ----------- Simple square wave tone generation is possible for up to 8 channels using diff --git a/libraries/rp2040/examples/GPIOInvert/GPIOInvert.ino b/libraries/rp2040/examples/GPIOInvert/GPIOInvert.ino new file mode 100644 index 000000000..9a5570c4c --- /dev/null +++ b/libraries/rp2040/examples/GPIOInvert/GPIOInvert.ino @@ -0,0 +1,37 @@ + +/* + GPIOInvert + + This example shows how to enable the pin output inversion mechanism for a GPIO pin. + + This example code is in the public domain. +*/ + +int led = LED_BUILTIN; // the pin the LED is attached to + +// the setup routine runs once when you press reset: +void setup() { + // declare pin to be an output: + pinMode(led, OUTPUT); + // Now enable the pin inversion function. + // This must be done after the pinMode command. + setPinInvert(led, true); + + while(!Serial) + delay(10); + + Serial.begin(115200); +} + +// the loop routine runs over and over again forever: +void loop() { + // Turn the LED off + digitalWrite(led, HIGH); + Serial.println("LED off"); + delay(2000); + + // Turn the LED on + digitalWrite(led, LOW); + Serial.println("LED on"); + delay(2000); +} \ No newline at end of file