Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

displayio.I2CDisplay raises TypeError when called with TCA9548A I2C port #9172

Open
timchinowsky opened this issue Apr 12, 2024 · 9 comments

Comments

@timchinowsky
Copy link

timchinowsky commented Apr 12, 2024

CircuitPython version

Adafruit CircuitPython 9.0.0 on 2024-03-19; Waveshare RP2040-Zero with rp2040

Code/REPL

import adafruit_tca9548a                                                                                                                               
import board                                                                                                                                           
import busio                                                                                                                                           
import displayio                                                                                                                                       
                                                                                                                                                       
i2c = busio.I2C(board.GP1, board.GP0)                                                                                                                  
tca = adafruit_tca9548a.TCA9548A(i2c)                                                                                                                  
display_bus = displayio.I2CDisplay(tca[3], device_address=0x3C)

Behavior

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: i2c_bus must be of type I2C, not TCA9548A_Channel

Description

Looks like I2CDisplay is not tolerant of the I2C abstraction returned by the driver for the TCA9548A I2C multiplexer.

Additional information

Guessing this is due to type checking added in b799b2e

@dhalbert dhalbert added this to the 9.x.x milestone Apr 18, 2024
@dhalbert
Copy link
Collaborator

@tannewt is it possible to use duck-typing here?

@tannewt
Copy link
Member

tannewt commented Apr 22, 2024

@tannewt is it possible to use duck-typing here?

Not in the short term. Generally native modules need native implementations because they call functions on the other native object directly. Displays are extra difficult currently because we assume they all can run without a VM. Python-implemented APIs won't work in this case.

There is a future I can see where we do allow Python I2C busses but that requires us to use the Python function lookup instead of direct calls and it requires us to allow VM-only displays.

@tannewt tannewt modified the milestones: 9.x.x, Long term Apr 22, 2024
@timchinowsky
Copy link
Author

Unfamiliar with the history and architecture here, can you explain how/why displayio.I2CDisplay(tca[3], device_address=0x3C) differs in this respect from the older adafruit_ssd1306.SSD1306_I2C(128, 32, tca[3]), which works just fine? Thanks!

@tannewt
Copy link
Member

tannewt commented Apr 25, 2024

Unfamiliar with the history and architecture here, can you explain how/why displayio.I2CDisplay(tca[3], device_address=0x3C) differs in this respect from the older adafruit_ssd1306.SSD1306_I2C(128, 32, tca[3]), which works just fine? Thanks!

displayio is a module implemented in the core using C. adafruit_ssd1306 is a pure Python module.

@timchinowsky
Copy link
Author

Are there any native modules which do use the Python function lookup in the way that would be required? And, are there adafruit_* modules which are not pure Python, i.e. use native code?

@tannewt
Copy link
Member

tannewt commented Apr 26, 2024

Are there any native modules which do use the Python function lookup in the way that would be required?

adafruit_bus_device does this correctly:

mp_load_method(self->i2c, MP_QSTR_writeto, dest);
dest[2] = MP_OBJ_NEW_SMALL_INT(self->device_address);
dest[3] = write_buffer;
mp_call_method_n_kw(2, 0, dest);
nlr_pop();

displayio has the added challenge of running when no VM is present as well.

And, are there adafruit_* modules which are not pure Python, i.e. use native code?

There are only two currently: adafruit_bus_device and adafruit_pypixelbuf. We have both native and Python versions of them.

@timchinowsky
Copy link
Author

displayio has the added challenge of running when no VM is present as well.

Why does it need to be able to do that?

@tannewt
Copy link
Member

tannewt commented Apr 26, 2024

displayio has the added challenge of running when no VM is present as well.

Why does it need to be able to do that?

We automatically show errors on the display after the VM finishes. It shows the CircuitPython terminal. We have plans to make this behavior more explicit but it won't happen soon.

@timchinowsky
Copy link
Author

Ah, great background, thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants