I’ve never looked at MicroPython code before, but it appears that there are multiple problems in mod_machine_pin.c. In particular, in machine_pin_obj_init_helper() where the pullups appear to need to be handled.
The first (and easiest) problem has to do with the comment “// set initial value (do this before configuring mode/pull)” has to be incorrect, because the code does the opposite of what this comment says to do. On the ATmega328, this order of setting the DDRx and PORTx bits was important because of the kludge of using PORTx as the pullup register control when you wanted to switch the pin direction from INPUT* to OUTPUT, because you might have to go through a bus cycle where the output could be driven momentarily with the wrong value before the correct one was established. Fortunately this problem was eliminated by giving pullups/downs their own register(s) in SAMD.
I believe that the correct fix for this is to move the if-statement for setting the value to be before the mode is set, as the comment states. The if-statement condition here seems like it could (or should) also be changed from “ARG_value != NULL” to add “&& ARG_mode==OUTPUT”, because no digitalWrite() needs to be done here if the mode isn’t OUTPUT.
The second (and originally discovered problem) is that turning on pull-ups/downs does not appear to be coded here anywhere in Pin…
It seems like the general flow of the initialization should be (sorry, but it doesn’t look like Preformatted Text is working below):
if (mode == none) {
return error
}
if (mode == OUTPUT) {
if (value != NULL) {
digitalWrite(value)
}
pinMode(OUTPUT)
}
else {
pinMode(mode) // either INPUT or INPUT_PULLUP
}
Lastly, it seems like there are a lot of possibilities for out of range input parameters – namely mode not OUTPUT, INPUT or INPUT_PULLUP, value not being 0 or 1, or a value being specified if mode != OUTPUT. However, I don’t know if these are all treated as “user beware” as a (conscious) matter of policy or not, or if this idiot-checking is done elsewhere, or…
By the way, I was able to find a combination of parameters that actually enables me to turn on the pullups using the existing buggy implementation, but this only works because the Arduino core has grandfathered the behavior of pinMode(INPUT) followed by a digitalWrite(HIGH) to turn on the pullups as was originally required for the ATmega328 before pinMode(INPUT_PULLUP) existed. Knowing this I was able to trick the current ArduPy code (which makes no sense as ArduPy/MicroPython code) to do what I wanted. That is, if you use:
Pin(p, Pin.IN, pull=Pin.PULL_UP, value=1)
So, until Pin.init gets fixed, at least I have a workaround…
Hope that helps,
-e