pi4j-v2 icon indicating copy to clipboard operation
pi4j-v2 copied to clipboard

Multipurpose (Input & Output) GPIO

Open treitmaier opened this issue 4 years ago • 7 comments

The Context I'm in the process of porting the libraries of Skywriter & Flick I2C gesture sensing boards from python to Java/pi4j. Both boards utilise the MGC3130 chipset.

The Problem The MGC3130 chipset requires the transfer pin (BCM 27) to be used as both input and output within each polling cycle. At the start of the cycle the library waits for a low transfer line (input). However, the library then reconfigures the same pin (BCM27) as a low output to assert that the MGC3130 does not update data buffers before reading from them.

The Issue Does pi4j-v2 support Multipurpose GPIO that can be reconfigured to work as input and output?

treitmaier avatar Jul 06 '20 07:07 treitmaier

Thanks for your question! And nice to see you are working on these libraries using Pi4J!

As you can see in https://github.com/Pi4J/pi4j-v2/tree/master/pi4j-core/src/main/java/com/pi4j/io/gpio/digital currently we only have input or output types. Would it be an idea to reconfigure the I/O in your library itself between each action? I've not done this myself before so no idea what the behavior would be and if this happens fast enough.

FYI, under the hood, Pi4J V2 is using http://abyz.me.uk/rpi/pigpio/ so anything supported by that library should also be available in Pi4J or could be added.

FDelporte avatar Jul 07 '20 10:07 FDelporte

I remember something like this in Pi4J V1.
See: https://github.com/Pi4J/pi4j/search?q=GpioPinDigitalMultipurpose&unscoped_q=GpioPinDigitalMultipurpose

We probably should consider this for V2 as well.

savageautomate avatar Jul 07 '20 14:07 savageautomate

Thanks for your comments @savageautomate & @FDelporte . It looks like pigpio would support Multipurpose GPIOs through its gpioGetMode and gpioSetMode methods.

An unscoped code search for GpioPinDigitalMultipurpose reveal broad use-cases that would motivate such a feature in pi4j-v2. In particular matrix keypad drivers -- at least the more sophisticated ones -- need to switch between input and output modes while scanning for keypresses.

The driver I ported to pi4j-v2 seems to be working OK just leaving the transfer line in input mode and ignoring the spec to switch it to output mode while reading from the chipset buffer. So there is no direct need from my end. However, I'd be happy to test any implementation on the driver I ported as well as on a matrix keypad that I have from on old project.

treitmaier avatar Jul 08 '20 08:07 treitmaier

I have added API support for Multipurpose pins in this branch: https://github.com/Pi4J/pi4j-v2/tree/issue/%2326

~~TODO: Still needs to be implemented in PIGPIO provider plugin.~~

savageautomate avatar Jul 09 '20 22:07 savageautomate

Added PIGPIO plugin implementation for Multipurpose GPIO pins.

TODO: Still needs to be tested on hardware.

savageautomate avatar Jul 10 '20 13:07 savageautomate

Thanks for all the hard work implementing the feature so quickly @savageautomate. I started to test it, but then ran into unhandled signal 11 errors, especially on aarch64 systems. Yesterday I saw that you had addressed a similar issue in the master branch. This morning I ran tests on the driver I'm implementing using the following pi4j-v2 libraries:

git checkout issue/#26
git rebase master
mvn clean install -Pnative,cross-compile

No more unhandled signal 11 errors and anecdotally my driver seems to function more robustly. In my particular use case switching the MultipurposePin from Input to Output (low) asserts that buffers aren't updated before the I2C read operation completes.

Looking at the implementation of the python driver, they switch the GPIO back to input (PULL_UP) after the I2C read operation completes.

I noticed that on your API I can switch to the DigitalMultipurpose back to input multipurpose.input(), but there isn't a way to specify pull up/down resistance at this point. I guess I can set the resistance initially like so:

var multipurpose = DigitalMultipurpose.newConfigBuilder(pi4j)
        .id("transfer")
        .name("transfer")
        .address(5)
        .mode(DigitalMode.INPUT)
        .pull(PullResistance.PULL_UP)
        .provider(PiGpioPlugin.DIGITAL_MULTIPURPOSE_PROVIDER_ID);

but am wondering if this configuration persists even after switching the multipurpose pin between input and output.

treitmaier avatar Jul 17 '20 08:07 treitmaier

@treitmaier ,

Just a note on mvn clean install -Pnative,cross-compile .. this won't currently build proper binaries for 32-bit armhf for ARMv6 devices. (See Issue #28)

The following will if you run from an amd64/x86_64 based machine with Docker installed:

`mvn clean install -Pnative,docker`

This may not matter to you since you are working on aarch64, but just wanted you to be aware.


I noticed that on your API I can switch to the DigitalMultipurpose back to input multipurpose.input(), but there isn't a way to specify pull up/down resistance at this point. I guess I can set the resistance initially like so:

That's a good question. Pi4J V2 will only explicitly configure the digital input pin with its PULL config at the time of initialization. Switching to OUTPUT mode then back to INPUT does not re-apply the PULL config (or DEBOUNCE config) ... at least not in Pi4J code.

https://github.com/Pi4J/pi4j-v2/blob/b406d7f741d96eb5bfa6c13d7e16be5bf702adb3/plugins/pi4j-plugin-pigpio/src/main/java/com/pi4j/plugin/pigpio/provider/gpio/digital/PiGpioDigitalMultipurpose.java#L94-L116

So I don't technically know if the mode change by the underlying PiGPIO library will modify PULL resistance or the DEBOUNCE settings. Do you think we should just go ahead and manually re-apply these settings anytime the multipurpose pin is returned to the INPUT mode?

savageautomate avatar Jul 17 '20 14:07 savageautomate