diff --git a/ports/raspberrypi/boards/pimoroni_keybow2040/mpconfigboard.mk b/ports/raspberrypi/boards/pimoroni_keybow2040/mpconfigboard.mk index cf742943150ec..8e01342e5e84f 100644 --- a/ports/raspberrypi/boards/pimoroni_keybow2040/mpconfigboard.mk +++ b/ports/raspberrypi/boards/pimoroni_keybow2040/mpconfigboard.mk @@ -9,3 +9,6 @@ CHIP_FAMILY = rp2 INTERNAL_FLASH_FILESYSTEM = 1 CIRCUITPY__EVE = 1 + +CIRCUITPY_REQUIRE_I2C_PULLUPS ?= 0 +CIRCUITPY_BUSIO_I2C_INTERNAL_PULLUPS ?= 1 diff --git a/ports/raspberrypi/common-hal/busio/I2C.c b/ports/raspberrypi/common-hal/busio/I2C.c index c9f89fadd8da2..2bd6383c37fe2 100644 --- a/ports/raspberrypi/common-hal/busio/I2C.c +++ b/ports/raspberrypi/common-hal/busio/I2C.c @@ -98,13 +98,20 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, } #endif - // Create a bitbangio.I2C object to do short writes. + // Create a bitbangio.I2C object to do 0 byte writes. + // + // These are used to non-invasively detect I2C devices by sending + // the address and confirming an ACK. + // They are not supported by the RP2040 hardware. + // // Must be done before setting up the I2C pins, since they will be // set up as GPIO by the bitbangio.I2C object. // // Sets pins to open drain, high, and input. +#ifndef CIRCUITPY_BUSIO_I2C_INTERNAL_PULLUPS shared_module_bitbangio_i2c_construct(&self->bitbangio_i2c, scl, sda, - frequency, timeout); + frequency, timeout); +#endif self->baudrate = i2c_init(self->peripheral, frequency); @@ -115,6 +122,11 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, gpio_set_function(self->scl_pin, GPIO_FUNC_I2C); gpio_set_function(self->sda_pin, GPIO_FUNC_I2C); + +#if CIRCUITPY_BUSIO_I2C_INTERNAL_PULLUPS + gpio_set_pulls(self->scl_pin, true, false); + gpio_set_pulls(self->sda_pin, true, false); +#endif } bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) { @@ -157,9 +169,11 @@ void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) { } uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, - const uint8_t *data, size_t len, bool transmit_stop_bit) { - if (len <= 2) { - // The RP2040 I2C peripheral will not do writes 2 bytes or less long. + const uint8_t *data, size_t len, bool transmit_stop_bit) { + +#ifndef CIRCUITPY_BUSIO_I2C_INTERNAL_PULLUPS + if (len == 0) { + // The RP2040 I2C peripheral will not perform 0 byte writes. // So use bitbangio.I2C to do the write. gpio_set_function(self->scl_pin, GPIO_FUNC_SIO); @@ -179,6 +193,7 @@ uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, return status; } +#endif int result = i2c_write_timeout_us(self->peripheral, addr, data, len, !transmit_stop_bit, BUS_TIMEOUT_US); if (result == len) { diff --git a/ports/raspberrypi/mpconfigport.mk b/ports/raspberrypi/mpconfigport.mk index bcfe3efd1e597..24a733129a456 100644 --- a/ports/raspberrypi/mpconfigport.mk +++ b/ports/raspberrypi/mpconfigport.mk @@ -23,6 +23,8 @@ else CIRCUITPY_NEOPIXEL_WRITE = 0 endif +CIRCUITPY_BUSIO_I2C_INTERNAL_PULLUPS_AVAILABLE ?= 1 + CIRCUITPY_FRAMEBUFFERIO = 1 CIRCUITPY_FULL_BUILD = 1 CIRCUITPY_AUDIOMP3 ?= 1 diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index eedda7ad73ec8..55bb8f228c819 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -314,6 +314,11 @@ extern const struct _mp_obj_module_t bitmaptools_module; #define BITMAPTOOLS_MODULE #endif +#if CIRCUITPY_BUSIO_I2C_INTERNAL_PULLUPS && !CIRCUITPY_BUSIO_I2C_INTERNAL_PULLUPS_AVAILABLE +#error "CIRCUITPY_BUSIO_I2C_INTERNAL_PULLUPS requires onboard pullups." \ + "Ensure board supports these and set CIRCUITPY_BUSIO_I2C_INTERNAL_PULLUPS_AVAILABLE = 1" +#endif + #if CIRCUITPY_BITOPS extern const struct _mp_obj_module_t bitops_module; #define BITOPS_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_bitops),(mp_obj_t)&bitops_module }, diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index fea1f937ec206..c665bdb80da43 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -121,6 +121,12 @@ CFLAGS += -DCIRCUITPY_BUILTINS_POW3=$(CIRCUITPY_BUILTINS_POW3) CIRCUITPY_BUSIO ?= 1 CFLAGS += -DCIRCUITPY_BUSIO=$(CIRCUITPY_BUSIO) +CIRCUITPY_BUSIO_I2C_INTERNAL_PULLUPS ?= 0 +CFLAGS += -DCIRCUITPY_BUSIO_I2C_INTERNAL_PULLUPS=$(CIRCUITPY_BUSIO_I2C_INTERNAL_PULLUPS) + +CIRCUITPY_BUSIO_I2C_INTERNAL_PULLUPS_AVAILABLE ?= 0 +CFLAGS += -DCIRCUITPY_BUSIO_I2C_INTERNAL_PULLUPS_AVAILABLE=$(CIRCUITPY_BUSIO_I2C_INTERNAL_PULLUPS_AVAILABLE) + CIRCUITPY_CAMERA ?= 0 CFLAGS += -DCIRCUITPY_CAMERA=$(CIRCUITPY_CAMERA)