I tried it just now on a Teensy 4.0. The code needs a minor edit, since the first if condition doesn't allow OUTPUT_1 to OUTPUT_7. To be used within a normal program, the function needs a different name so it doesn't conflict with the original pinMode().
I tested by connecting a 464 ohm resistor to GND and measuring the voltage for logic high. VCC was measured at 3.286. The drive strength does indeed change, though the impedance is lower (stronger drive) than NXP's documentation.
Code:
Ohms Ohms
Setting Claimed Voltage Actual
OUTPUT_1 400 2.588 125
OUTPUT_2 200 2.915 59
OUTPUT_4 104 3.107 27
OUTPUT_7 55 3.177 16
I tested only 1 board and only at room temperature. NXP's specs might be the worst case for all chips at max temperature?
Here's the code in the form of a complete working program. To recreate this measurement, just connect a 470 ohm resistor across a voltmeter and measure each pin's actual voltage.
Code:
#define HIGH 1
#define LOW 0
#define INPUT 0
#define OUTPUT 1
#define OUTPUT_1 11
#define OUTPUT_2 12
#define OUTPUT_3 13
#define OUTPUT_4 14
#define OUTPUT_5 15
#define OUTPUT_6 16
#define OUTPUT_7 17
#define INPUT_PULLUP 2
#define INPUT_PULLDOWN 3
#define OUTPUT_OPENDRAIN 4
#define INPUT_DISABLE 5
#define LSBFIRST 0
#define MSBFIRST 1
#define _BV(n) (1<<(n))
#define CHANGE 4
#define FALLING 2
#define RISING 3
void setup() {
pinModeExt(2, OUTPUT_1);
pinModeExt(3, OUTPUT_2);
pinModeExt(4, OUTPUT_4);
pinModeExt(5, OUTPUT_7);
digitalWrite(2, HIGH);
digitalWrite(3, HIGH);
digitalWrite(4, HIGH);
digitalWrite(5, HIGH);
}
void loop() {
// put your main code here, to run repeatedly:
}
void pinModeExt(uint8_t pin, uint8_t mode)
{
const struct digital_pin_bitband_and_config_table_struct *p;
if (pin >= CORE_NUM_DIGITAL) return;
p = digital_pin_to_info_PGM + pin;
if (mode == OUTPUT || mode == OUTPUT_OPENDRAIN || (mode >= OUTPUT_1 && mode <= OUTPUT_7))
{
*(p->reg + 1) |= p->mask; // TODO: atomic
if (mode == OUTPUT) // Default
{
*(p->pad) = IOMUXC_PAD_DSE(7);
}
else if (mode == OUTPUT_1) // 400 ohm
{
*(p->pad) = IOMUXC_PAD_DSE(1);
}
else if (mode == OUTPUT_2) // 200 ohm
{
*(p->pad) = IOMUXC_PAD_DSE(2);
}
else if (mode == OUTPUT_3) // 132 ohm
{
*(p->pad) = IOMUXC_PAD_DSE(3);
}
else if (mode == OUTPUT_4) // 104 ohm
{
*(p->pad) = IOMUXC_PAD_DSE(4);
}
else if (mode == OUTPUT_5) // 83 ohm
{
*(p->pad) = IOMUXC_PAD_DSE(5);
}
else if (mode == OUTPUT_6) // 70 ohm
{
*(p->pad) = IOMUXC_PAD_DSE(6);
}
else if (mode == OUTPUT_7) // 55 ohm - same as Default
{
*(p->pad) = IOMUXC_PAD_DSE(7);
}
else
{ // OUTPUT_OPENDRAIN
*(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_ODE;
}
}
else
{
*(p->reg + 1) &= ~(p->mask); // TODO: atomic
if (mode == INPUT)
{
*(p->pad) = IOMUXC_PAD_DSE(7);
}
else if (mode == INPUT_PULLUP)
{
*(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(3) | IOMUXC_PAD_HYS;
}
else if (mode == INPUT_PULLDOWN)
{
*(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(0) | IOMUXC_PAD_HYS;
}
else
{ // INPUT_DISABLE
*(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_HYS;
}
}
*(p->mux) = 5 | 0x10;
}