Skip to content

Commit 77ee965

Browse files
committed
add optional aditional I2C singletons
define DEFAULT_I2C_BUS for the number of I2C busses list the pins in a list DEFAULT_I2C_PINS macro to create a new I2C object singleton ADD_SINGLETON_I2C_OBJ check for I2C singleton in displayio
1 parent a084124 commit 77ee965

File tree

7 files changed

+83
-37
lines changed

7 files changed

+83
-37
lines changed

ports/raspberrypi/boards/adafruit_qtpy_rp2040/mpconfigboard.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
#define MICROPY_HW_NEOPIXEL (&pin_GPIO12)
55
#define CIRCUITPY_STATUS_LED_POWER (&pin_GPIO11)
66

7-
#define DEFAULT_I2C_BUS_SCL (&pin_GPIO25)
8-
#define DEFAULT_I2C_BUS_SDA (&pin_GPIO24)
7+
#define DEFAULT_I2C_BUS (2)
8+
// SCL, SDA, SCL1, SDA1
9+
#define DEFAULT_I2C_PINS { &pin_GPIO25, &pin_GPIO24, &pin_GPIO23, &pin_GPIO22 }
910

1011
#define DEFAULT_SPI_BUS_SCK (&pin_GPIO6)
1112
#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO3)

ports/raspberrypi/boards/adafruit_qtpy_rp2040/pins.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "shared-bindings/board/__init__.h"
22

3+
ADD_SINGLETON_I2C_OBJ(board_stemma_i2c_obj, 1)
4+
35
STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
46
CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS
57

@@ -45,6 +47,7 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
4547
{ MP_ROM_QSTR(MP_QSTR_SCL1), MP_ROM_PTR(&pin_GPIO23) },
4648

4749
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
50+
{ MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_stemma_i2c_obj) },
4851
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
4952
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
5053
};

py/circuitpy_mpconfig.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,10 +247,19 @@ typedef long mp_off_t;
247247
// So if any are not defined in *.mk, they'll throw an error here.
248248

249249
#if CIRCUITPY_BOARD
250-
#define BOARD_I2C (defined(DEFAULT_I2C_BUS_SDA) && defined(DEFAULT_I2C_BUS_SCL))
250+
251+
// support defining default I2C the old way without DEFAULT_I2C_BUS
252+
#if defined(DEFAULT_I2C_BUS_SDA) && defined(DEFAULT_I2C_BUS_SCL) \
253+
&& !defined(DEFAULT_I2C_BUS)
254+
#define DEFAULT_I2C_BUS (1)
255+
#define DEFAULT_I2C_PINS { DEFAULT_I2C_BUS_SCL, DEFAULT_I2C_BUS_SDA }
256+
#endif
257+
#define BOARD_I2C (defined(DEFAULT_I2C_BUS))
258+
251259
#define BOARD_SPI (defined(DEFAULT_SPI_BUS_SCK) && defined(DEFAULT_SPI_BUS_MISO) && defined(DEFAULT_SPI_BUS_MOSI))
252260
#define BOARD_UART (defined(DEFAULT_UART_BUS_RX) && defined(DEFAULT_UART_BUS_TX))
253261
// I2C and SPI are always allocated off the heap.
262+
254263
#if BOARD_UART
255264
#define BOARD_UART_ROOT_POINTER mp_obj_t shared_uart_bus;
256265
#else

shared-bindings/board/__init__.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,27 @@
5454
//| ...
5555
//|
5656

57+
//| def STEMMA_I2C() -> busio.I2C:
58+
//| """Returns the `busio.I2C` object for the STEMMA or STEMMA QT connector.
59+
//| Present only if the STEMMA connector provides a second, additional I2C bus that is not the same as `board.I2C()`.
60+
//| It is a singleton."""
61+
//| ...
62+
//|
63+
5764
#if BOARD_I2C
58-
mp_obj_t board_i2c(void) {
59-
mp_obj_t singleton = common_hal_board_get_i2c();
65+
extern mcu_pin_obj_t *i2c_default_pins[];
66+
67+
mp_obj_t board_i2c_n(int busnum) {
68+
mp_obj_t singleton = common_hal_board_get_i2c(busnum);
6069
if (singleton != NULL && !common_hal_busio_i2c_deinited(singleton)) {
6170
return singleton;
6271
}
63-
assert_pin_free(DEFAULT_I2C_BUS_SDA);
64-
assert_pin_free(DEFAULT_I2C_BUS_SCL);
65-
return common_hal_board_create_i2c();
72+
assert_pin_free(i2c_default_pins[busnum * 2]);
73+
assert_pin_free(i2c_default_pins[busnum * 2 + 1]);
74+
return common_hal_board_create_i2c(busnum);
75+
}
76+
mp_obj_t board_i2c(void) {
77+
return board_i2c_n(0);
6678
}
6779
#else
6880
mp_obj_t board_i2c(void) {

shared-bindings/board/__init__.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,18 @@
3535
extern const mp_obj_dict_t board_module_globals;
3636
STATIC const MP_DEFINE_STR_OBJ(board_module_id_obj, CIRCUITPY_BOARD_ID);
3737

38-
mp_obj_t common_hal_board_get_i2c(void);
39-
mp_obj_t common_hal_board_create_i2c(void);
38+
mp_obj_t common_hal_board_get_i2c(int);
39+
mp_obj_t common_hal_board_create_i2c(int);
4040
MP_DECLARE_CONST_FUN_OBJ_0(board_i2c_obj);
41+
bool common_hal_board_is_i2c_singleton(mp_obj_t compare_i2c);
42+
43+
#if BOARD_I2C
44+
extern mp_obj_t board_i2c_n(int busnum);
45+
#define ADD_SINGLETON_I2C_OBJ(name, n) mp_obj_t board_i2c_bus_##n(void) { \
46+
return board_i2c_n(n); \
47+
} \
48+
MP_DEFINE_CONST_FUN_OBJ_0(name, board_i2c_bus_##n);
49+
#endif
4150

4251
mp_obj_t common_hal_board_get_spi(void);
4352
mp_obj_t common_hal_board_create_spi(void);

shared-module/board/__init__.c

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -47,25 +47,35 @@
4747
#if BOARD_I2C
4848
// Statically allocate the I2C object so it can live past the end of the heap and into the next VM.
4949
// That way it can be used by built-in I2CDisplay displays and be accessible through board.I2C().
50-
STATIC busio_i2c_obj_t i2c_obj;
51-
STATIC mp_obj_t i2c_singleton = NULL;
50+
STATIC busio_i2c_obj_t i2c_obj[DEFAULT_I2C_BUS];
51+
STATIC mp_obj_t i2c_singleton[DEFAULT_I2C_BUS];
52+
const mcu_pin_obj_t *i2c_default_pins[DEFAULT_I2C_BUS * 2] = DEFAULT_I2C_PINS;
5253

53-
mp_obj_t common_hal_board_get_i2c(void) {
54-
return i2c_singleton;
54+
mp_obj_t common_hal_board_get_i2c(int busnum) {
55+
return i2c_singleton[busnum];
5556
}
5657

57-
mp_obj_t common_hal_board_create_i2c(void) {
58+
mp_obj_t common_hal_board_create_i2c(int busnum) {
5859
// All callers have either already verified this or come so early that it can't be otherwise.
59-
assert(i2c_singleton == NULL || common_hal_busio_i2c_deinited(i2c_singleton));
60-
busio_i2c_obj_t *self = &i2c_obj;
60+
assert(i2c_singleton[busnum] == NULL || common_hal_busio_i2c_deinited(i2c_singleton[busnum]));
61+
busio_i2c_obj_t *self = &i2c_obj[busnum];
6162
self->base.type = &busio_i2c_type;
6263

63-
common_hal_busio_i2c_construct(self, DEFAULT_I2C_BUS_SCL, DEFAULT_I2C_BUS_SDA, 100000, 255);
64-
i2c_singleton = (mp_obj_t)self;
65-
return i2c_singleton;
64+
common_hal_busio_i2c_construct(self, i2c_default_pins[busnum * 2], i2c_default_pins[busnum * 2 + 1], 100000, 255);
65+
i2c_singleton[busnum] = (mp_obj_t)self;
66+
return i2c_singleton[busnum];
6667
}
67-
#endif
6868

69+
bool common_hal_board_is_i2c_singleton(mp_obj_t compare_i2c) {
70+
// check that this object is one of the singletons (for displayio)
71+
for (int i2ci = 0; i2ci < DEFAULT_I2C_BUS; ++i2ci) {
72+
if (compare_i2c == i2c_singleton[i2ci]) {
73+
return true;
74+
}
75+
}
76+
return false;
77+
}
78+
#endif
6979

7080
#if BOARD_SPI
7181
// Statically allocate the SPI object so it can live past the end of the heap and into the next VM.
@@ -134,21 +144,23 @@ mp_obj_t common_hal_board_create_uart(void) {
134144

135145
void reset_board_busses(void) {
136146
#if BOARD_I2C
137-
bool display_using_i2c = false;
138-
#if CIRCUITPY_DISPLAYIO
139-
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
140-
if (displays[i].bus_base.type == &displayio_i2cdisplay_type && displays[i].i2cdisplay_bus.bus == i2c_singleton) {
141-
display_using_i2c = true;
142-
break;
147+
for (int i2ci = 0; i2ci < DEFAULT_I2C_BUS; ++i2ci) {
148+
bool display_using_i2c = false;
149+
#if CIRCUITPY_DISPLAYIO
150+
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
151+
if (displays[i].bus_base.type == &displayio_i2cdisplay_type && displays[i].i2cdisplay_bus.bus == i2c_singleton[i2ci]) {
152+
display_using_i2c = true;
153+
break;
154+
}
143155
}
144-
}
145-
#endif
146-
// make sure I2C lock is not held over a soft reset
147-
if (i2c_singleton != NULL) {
148-
common_hal_busio_i2c_unlock(i2c_singleton);
149-
if (!display_using_i2c) {
150-
common_hal_busio_i2c_deinit(i2c_singleton);
151-
i2c_singleton = NULL;
156+
#endif
157+
// make sure I2C lock is not held over a soft reset
158+
if (i2c_singleton[i2ci] != NULL) {
159+
common_hal_busio_i2c_unlock(i2c_singleton[i2ci]);
160+
if (!display_using_i2c) {
161+
common_hal_busio_i2c_deinit(i2c_singleton[i2ci]);
162+
i2c_singleton[i2ci] = NULL;
163+
}
152164
}
153165
}
154166
#endif

shared-module/displayio/__init__.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,10 @@ void reset_displays(void) {
165165
((uint32_t)i2c->bus) > ((uint32_t)&displays + CIRCUITPY_DISPLAY_LIMIT)) {
166166
busio_i2c_obj_t *original_i2c = i2c->bus;
167167
#if BOARD_I2C
168-
// We don't need to move original_i2c if it is the board.I2C object because it is
168+
// We don't need to move original_i2c if it is a board.I2C singletion because it is
169169
// statically allocated already. (Doing so would also make it impossible to reference in
170170
// a subsequent VM run.)
171-
if (original_i2c == common_hal_board_get_i2c()) {
171+
if (common_hal_board_is_i2c_singleton(original_i2c)) {
172172
continue;
173173
}
174174
#endif

0 commit comments

Comments
 (0)