adafruit / Adafruit_Blinka

Add CircuitPython hardware API and libraries to MicroPython & CPython devices
https://learn.adafruit.com/circuitpython-on-raspberrypi-linux
MIT License
438 stars 328 forks source link

Open drain output on a Raspberry Pi requires value setting of an input pin #794

Closed CompThing closed 3 months ago

CompThing commented 3 months ago

Board Name

Raspberry Pi 4

Steps

I have a Raspberry Pi GPIO pin connected to a switched input on another board. The other board has a pull-up resistor on its input, and operating the switch will connect the pin to ground. The digitalio library blocks the use of a Raspberry Pi GPIO mode by disallowing the setting of value prior to setting the direction to output.

Description

I need the Raspberry Pi GPIO pin to switch beween floating and low. Some microcontrollers support outputs operating in an open-drain mode to acheive this. However, the Raspberry Pi do not have that mode. Equivalent operation has traditionally been achieved by switching a GPIO pin from INPUT to OUTPUT LOW in an atomic action. That requires a 0 output value prior to switching from input to output, to avoid a transition via output=1. The DigitalIO implementation blocks that atomic action via the following code: @value.setter def value(self, val): if self.direction is Direction.OUTPUT: self._pin.value(1 if val else 0) else: raise AttributeError("Not an output") That prevents setting of value prior to changing the direction to output. It is therefore not possible to prevent a transient output of 1.

Additional information

Allowing value to be configured for a pin while it is still an input is required for implementing open drain output on a Raspberry Pi. It is also good practice to configure values for outputs prior to enabling outputs. I have worked on a project before where an IO line was used for handshaking between devices. Enabling outputs prior to setting values resulted in a transient where one device drove the IO line high while the other pulled it low resulting in short circuit preotection circutiry kicking in

CompThing commented 3 months ago

The check on if self.direction is Direction.OUTPUT: is also inappropriate for the drive_mode.setter method. It should be possible to configure drive mode prior to configuring the pin as an output.

makermelissa commented 3 months ago

This is the intended behavior because it matches the behavior of CircuitPython, which is the whole point of Blinka. If you need it to work in a different way, you can either modify the code for your needs or create a copy of digitalio that works in the way you need. Digitalio is not a library that changes often, so you should be fine with not worrying about having to maintain a copy of digitalio.