Skip to content

Commit e2eb5ba

Browse files
committed
Set CIRCUITPY_DISPLAY_LIMIT in settings.toml
1 parent ed2ae0d commit e2eb5ba

File tree

6 files changed

+84
-30
lines changed

6 files changed

+84
-30
lines changed

main.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,6 +1057,11 @@ int __attribute__((used)) main(void) {
10571057
reset_devices();
10581058
reset_board();
10591059

1060+
#if CIRCUITPY_DISPLAYIO
1061+
// If number of displays has been overriden in settings.toml allocate memory and dynamic memory
1062+
malloc_display_memory();
1063+
#endif
1064+
10601065
// displays init after filesystem, since they could share the flash SPI
10611066
board_init();
10621067

shared-module/board/__init__.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
#include "mpconfigboard.h"
1111
#include "py/runtime.h"
1212

13+
#if CIRCUITPY_OS_GETENV
14+
#include "shared-module/os/__init__.h"
15+
#endif
16+
1317
#if CIRCUITPY_BUSIO
1418
#include "shared-bindings/busio/I2C.h"
1519
#include "shared-bindings/busio/SPI.h"
@@ -172,11 +176,19 @@ mp_obj_t common_hal_board_create_uart(const mp_int_t instance) {
172176
#endif
173177

174178
void reset_board_buses(void) {
179+
#if CIRCUITPY_BOARD_I2C || CIRCUITPY_BOARD_SPI
180+
mp_int_t max_num_displays = CIRCUITPY_DISPLAY_LIMIT;
181+
182+
#if CIRCUITPY_OS_GETENV
183+
(void)common_hal_os_getenv_int("CIRCUITPY_DISPLAY_LIMIT", &max_num_displays);
184+
#endif
185+
#endif
186+
175187
#if CIRCUITPY_BOARD_I2C
176188
for (uint8_t instance = 0; instance < CIRCUITPY_BOARD_I2C; instance++) {
177189
bool display_using_i2c = false;
178190
#if CIRCUITPY_I2CDISPLAYBUS
179-
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
191+
for (uint8_t i = 0; i < max_num_displays; i++) {
180192
if (display_buses[i].bus_base.type == &i2cdisplaybus_i2cdisplaybus_type && display_buses[i].i2cdisplay_bus.bus == &i2c_obj[instance]) {
181193
display_using_i2c = true;
182194
break;
@@ -197,7 +209,7 @@ void reset_board_buses(void) {
197209
for (uint8_t instance = 0; instance < CIRCUITPY_BOARD_SPI; instance++) {
198210
bool display_using_spi = false;
199211
#if CIRCUITPY_FOURWIRE || CIRCUITPY_SHARPDISPLAY || CIRCUITPY_AURORA_EPAPER
200-
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
212+
for (uint8_t i = 0; i < max_num_displays; i++) {
201213
mp_const_obj_t bus_type = display_buses[i].bus_base.type;
202214
#if CIRCUITPY_FOURWIRE
203215
if (bus_type == &fourwire_fourwire_type && display_buses[i].fourwire_bus.bus == &spi_obj[instance]) {

shared-module/displayio/__init__.c

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222

2323
#include "py/mpconfig.h"
2424

25+
#if CIRCUITPY_OS_GETENV
26+
#include "shared-module/os/__init__.h"
27+
#endif
28+
2529
#if CIRCUITPY_BUSDISPLAY
2630
#include "shared-bindings/busdisplay/BusDisplay.h"
2731
#endif
@@ -46,9 +50,12 @@
4650

4751
// The default indicates no primary display
4852
static int primary_display_number = -1;
53+
static int max_num_displays = CIRCUITPY_DISPLAY_LIMIT;
4954

50-
primary_display_bus_t display_buses[CIRCUITPY_DISPLAY_LIMIT];
51-
primary_display_t displays[CIRCUITPY_DISPLAY_LIMIT];
55+
primary_display_bus_t display_busesx[CIRCUITPY_DISPLAY_LIMIT];
56+
primary_display_t displaysx[CIRCUITPY_DISPLAY_LIMIT];
57+
primary_display_bus_t *display_buses = &display_busesx[0];
58+
primary_display_t *displays = &displaysx[0];
5259

5360
displayio_buffer_transform_t null_transform = {
5461
.x = 0,
@@ -65,7 +72,7 @@ displayio_buffer_transform_t null_transform = {
6572

6673
#if CIRCUITPY_RGBMATRIX || CIRCUITPY_IS31FL3741 || CIRCUITPY_VIDEOCORE || CIRCUITPY_PICODVI
6774
static bool any_display_uses_this_framebuffer(mp_obj_base_t *obj) {
68-
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
75+
for (uint8_t i = 0; i < max_num_displays; i++) {
6976
if (displays[i].display_base.type == &framebufferio_framebufferdisplay_type) {
7077
framebufferio_framebufferdisplay_obj_t *display = &displays[i].framebuffer_display;
7178
if (display->framebuffer == obj) {
@@ -87,7 +94,7 @@ void displayio_background(void) {
8794
return;
8895
}
8996

90-
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
97+
for (uint8_t i = 0; i < max_num_displays; i++) {
9198
mp_const_obj_t display_type = displays[i].display_base.type;
9299
if (display_type == NULL || display_type == &mp_type_NoneType) {
93100
// Skip null display.
@@ -117,7 +124,7 @@ static void common_hal_displayio_release_displays_impl(bool keep_primary) {
117124
if (!keep_primary) {
118125
primary_display_number = -1;
119126
}
120-
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
127+
for (uint8_t i = 0; i < max_num_displays; i++) {
121128
if (i == primary_display_number) {
122129
continue;
123130
}
@@ -139,7 +146,7 @@ static void common_hal_displayio_release_displays_impl(bool keep_primary) {
139146
}
140147
displays[i].display_base.type = &mp_type_NoneType;
141148
}
142-
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
149+
for (uint8_t i = 0; i < max_num_displays; i++) {
143150
mp_const_obj_t bus_type = display_buses[i].bus_base.type;
144151
if (bus_type == NULL || bus_type == &mp_type_NoneType) {
145152
continue;
@@ -190,20 +197,32 @@ void common_hal_displayio_release_displays(void) {
190197
common_hal_displayio_release_displays_impl(false);
191198
}
192199

200+
void malloc_display_memory(void) {
201+
#if CIRCUITPY_OS_GETENV
202+
(void)common_hal_os_getenv_int("CIRCUITPY_DISPLAY_LIMIT", &max_num_displays);
203+
if (max_num_displays > CIRCUITPY_DISPLAY_LIMIT) {
204+
display_buses = (primary_display_bus_t*)port_malloc(sizeof(primary_display_bus_t) * max_num_displays, false);
205+
displays = (primary_display_t*)port_malloc(sizeof(primary_display_t) * max_num_displays, false);
206+
memcpy(display_buses, &display_busesx[0], sizeof(primary_display_bus_t) * max_num_displays);
207+
memcpy(displays, &displaysx[0], sizeof(primary_display_t) * max_num_displays);
208+
}
209+
#endif
210+
}
211+
193212
void reset_displays(void) {
194213
// In CircuitPython 10, release secondary displays before doing anything else:
195214
// common_hal_displayio_release_displays_impl(true);
196215

197216
// The SPI buses used by FourWires may be allocated on the heap so we need to move them inline.
198-
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
217+
for (uint8_t i = 0; i < max_num_displays; i++) {
199218
mp_const_obj_t display_bus_type = display_buses[i].bus_base.type;
200219
if (display_bus_type == NULL || display_bus_type == &mp_type_NoneType) {
201220
continue;
202221
#if CIRCUITPY_FOURWIRE
203222
} else if (display_bus_type == &fourwire_fourwire_type) {
204223
fourwire_fourwire_obj_t *fourwire = &display_buses[i].fourwire_bus;
205224
if (((size_t)fourwire->bus) < ((size_t)&display_buses) ||
206-
((size_t)fourwire->bus) > ((size_t)&display_buses + CIRCUITPY_DISPLAY_LIMIT * sizeof(primary_display_bus_t))) {
225+
((size_t)fourwire->bus) > ((size_t)&display_buses + max_num_displays * sizeof(primary_display_bus_t))) {
207226
busio_spi_obj_t *original_spi = fourwire->bus;
208227
#if CIRCUITPY_BOARD_SPI
209228
// We don't need to move original_spi if it is a board.SPI object because it is
@@ -221,7 +240,7 @@ void reset_displays(void) {
221240
memcpy(&fourwire->inline_bus, original_spi, sizeof(busio_spi_obj_t));
222241
fourwire->bus = &fourwire->inline_bus;
223242
// Check for other display buses that use the same spi bus and swap them too.
224-
for (uint8_t j = i + 1; j < CIRCUITPY_DISPLAY_LIMIT; j++) {
243+
for (uint8_t j = i + 1; j < max_num_displays; j++) {
225244
if (display_buses[j].fourwire_bus.base.type == &fourwire_fourwire_type &&
226245
display_buses[j].fourwire_bus.bus == original_spi) {
227246
display_buses[j].fourwire_bus.bus = &fourwire->inline_bus;
@@ -234,7 +253,7 @@ void reset_displays(void) {
234253
i2cdisplaybus_i2cdisplaybus_obj_t *i2c = &display_buses[i].i2cdisplay_bus;
235254
// Check to see if we need to inline the I2C bus.
236255
if (((size_t)i2c->bus) < ((size_t)&display_buses) ||
237-
((size_t)i2c->bus) > ((size_t)&display_buses + CIRCUITPY_DISPLAY_LIMIT * sizeof(primary_display_bus_t))) {
256+
((size_t)i2c->bus) > ((size_t)&display_buses + max_num_displays * sizeof(primary_display_bus_t))) {
238257
busio_i2c_obj_t *original_i2c = i2c->bus;
239258
#if CIRCUITPY_BOARD_I2C
240259
// We don't need to move original_i2c if it is a board.I2C object because it is
@@ -247,7 +266,7 @@ void reset_displays(void) {
247266
memcpy(&i2c->inline_bus, original_i2c, sizeof(busio_i2c_obj_t));
248267
i2c->bus = &i2c->inline_bus;
249268
// Check for other displays that use the same i2c bus and swap them too.
250-
for (uint8_t j = i + 1; j < CIRCUITPY_DISPLAY_LIMIT; j++) {
269+
for (uint8_t j = i + 1; j < max_num_displays; j++) {
251270
if (display_buses[j].i2cdisplay_bus.base.type == &i2cdisplaybus_i2cdisplaybus_type &&
252271
display_buses[j].i2cdisplay_bus.bus == original_i2c) {
253272
display_buses[j].i2cdisplay_bus.bus = &i2c->inline_bus;
@@ -271,7 +290,7 @@ void reset_displays(void) {
271290
is31fl3741_framebuffer_obj_t *is31fb = &display_buses[i].is31fl3741;
272291

273292
if (((uint32_t)is31fb->is31fl3741->i2c) < ((uint32_t)&display_buses) ||
274-
((uint32_t)is31fb->is31fl3741->i2c) > ((uint32_t)&display_buses + CIRCUITPY_DISPLAY_LIMIT)) {
293+
((uint32_t)is31fb->is31fl3741->i2c) > ((uint32_t)&display_buses + max_num_displays)) {
275294
#if CIRCUITPY_BOARD_I2C
276295
// We don't need to move original_i2c if it is the board.I2C object because it is
277296
// statically allocated already. (Doing so would also make it impossible to reference in
@@ -334,7 +353,7 @@ void reset_displays(void) {
334353
}
335354
}
336355

337-
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
356+
for (uint8_t i = 0; i < max_num_displays; i++) {
338357
// Reset the displayed group. Only the first will get the terminal but
339358
// that's ok.
340359
mp_const_obj_t display_type = displays[i].display_base.type;
@@ -358,7 +377,7 @@ void reset_displays(void) {
358377
}
359378

360379
void displayio_gc_collect(void) {
361-
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
380+
for (uint8_t i = 0; i < max_num_displays; i++) {
362381
mp_const_obj_t display_bus_type = display_buses[i].bus_base.type;
363382
if (display_bus_type == NULL || display_bus_type == &mp_type_NoneType) {
364383
continue;
@@ -385,7 +404,7 @@ void displayio_gc_collect(void) {
385404
#endif
386405
}
387406

388-
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
407+
for (uint8_t i = 0; i < max_num_displays; i++) {
389408
mp_const_obj_t display_type = displays[i].display_base.type;
390409
if (display_type == NULL || display_type == &mp_type_NoneType) {
391410
continue;
@@ -413,7 +432,7 @@ static bool is_display_active(mp_obj_base_t *display_maybe) {
413432
}
414433

415434
primary_display_t *allocate_display(void) {
416-
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
435+
for (uint8_t i = 0; i < max_num_displays; i++) {
417436
if (!is_display_active(&displays[i].display_base)) {
418437
// Clear this memory so it is in a known state before init.
419438
memset(&displays[i], 0, sizeof(displays[i]));
@@ -434,7 +453,7 @@ primary_display_t *allocate_display_or_raise(void) {
434453
}
435454

436455
primary_display_bus_t *allocate_display_bus(void) {
437-
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
456+
for (uint8_t i = 0; i < max_num_displays; i++) {
438457
mp_const_obj_t display_bus_type = display_buses[i].bus_base.type;
439458
if (display_bus_type == NULL || display_bus_type == &mp_type_NoneType) {
440459
// Clear this memory so it is in a known state before init.
@@ -455,7 +474,7 @@ primary_display_bus_t *allocate_display_bus_or_raise(void) {
455474
}
456475

457476
mp_obj_t common_hal_displayio_get_primary_display(void) {
458-
if (primary_display_number == -1 || primary_display_number >= CIRCUITPY_DISPLAY_LIMIT) {
477+
if (primary_display_number == -1 || primary_display_number >= max_num_displays) {
459478
return mp_const_none;
460479
}
461480
mp_obj_base_t *primary_display = &displays[primary_display_number].display_base;
@@ -470,7 +489,7 @@ void common_hal_displayio_set_primary_display(mp_obj_t new_primary_display) {
470489
primary_display_number = -1;
471490
return;
472491
}
473-
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
492+
for (uint8_t i = 0; i < max_num_displays; i++) {
474493
mp_obj_t display = MP_OBJ_FROM_PTR(&displays[i]);
475494
if (new_primary_display == display && is_display_active(display)) {
476495
primary_display_number = i;
@@ -485,7 +504,7 @@ void common_hal_displayio_auto_primary_display(void) {
485504
if (primary_display_number != -1) {
486505
return;
487506
}
488-
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
507+
for (uint8_t i = 0; i < max_num_displays; i++) {
489508
if (is_display_active(&displays[i].display_base)) {
490509
primary_display_number = i;
491510
return;

shared-module/displayio/__init__.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,16 @@ typedef struct {
9999
};
100100
} primary_display_t;
101101

102-
extern primary_display_bus_t display_buses[CIRCUITPY_DISPLAY_LIMIT];
103-
extern primary_display_t displays[CIRCUITPY_DISPLAY_LIMIT];
102+
extern primary_display_bus_t display_busesx[];
103+
extern primary_display_t displaysx[];
104+
extern primary_display_bus_t *display_buses;
105+
extern primary_display_t *displays;
104106

105107
extern displayio_group_t circuitpython_splash;
106108

107109
void displayio_background(void);
108110
void reset_displays(void);
111+
void malloc_display_memory(void);
109112
void displayio_gc_collect(void);
110113

111114
primary_display_t *allocate_display(void);

shared-module/epaperdisplay/EPaperDisplay.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
#include "supervisor/usb.h"
2121
#endif
2222

23+
#if CIRCUITPY_OS_GETENV
24+
#include "shared-module/os/__init__.h"
25+
#endif
26+
2327
#include <stdint.h>
2428
#include <string.h>
2529

@@ -501,7 +505,13 @@ void epaperdisplay_epaperdisplay_collect_ptrs(epaperdisplay_epaperdisplay_obj_t
501505
}
502506

503507
size_t maybe_refresh_epaperdisplay(void) {
504-
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
508+
mp_int_t max_num_displays = CIRCUITPY_DISPLAY_LIMIT;
509+
510+
#if CIRCUITPY_OS_GETENV
511+
(void)common_hal_os_getenv_int("CIRCUITPY_DISPLAY_LIMIT", &max_num_displays);
512+
#endif
513+
514+
for (uint8_t i = 0; i < max_num_displays; i++) {
505515
if (displays[i].epaper_display.base.type != &epaperdisplay_epaperdisplay_type ||
506516
displays[i].epaper_display.core.current_group != &circuitpython_splash) {
507517
// Skip regular displays and those not showing the splash.

supervisor/shared/web_workflow/web_workflow.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1554,24 +1554,29 @@ static void _process_request(socketpool_socket_obj_t *socket, _request *request)
15541554
}
15551555

15561556
static bool supervisor_filesystem_access_could_block(void) {
1557+
bool could_block = false;
15571558
#if CIRCUITPY_FOURWIRE
15581559
mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table);
15591560
if (!vfs->next) {
15601561
// Assume that the CIRCUITPY root is not sharing a SPI bus with the display SPI bus
15611562
return false;
15621563
}
1563-
// Check display 0 to see if it's on a fourwire (SPI) bus. If it is, blocking is possible
1564-
// in theory other displays could block but also in reality there's generally 0 or 1 displays
1565-
for (size_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
1564+
1565+
mp_int_t max_num_displays = CIRCUITPY_DISPLAY_LIMIT;
1566+
#if CIRCUITPY_OS_GETENV
1567+
(void)common_hal_os_getenv_int("CIRCUITPY_DISPLAY_LIMIT", &max_num_displays);
1568+
#endif
1569+
// Check displays to see if it's on a fourwire (SPI) bus. If it is, blocking is possible
1570+
for (size_t i = 0; i < max_num_displays; i++) {
15661571
if (display_buses[i].bus_base.type != &fourwire_fourwire_type) {
15671572
continue;
15681573
}
15691574
if (!common_hal_fourwire_fourwire_bus_free(MP_OBJ_FROM_PTR(&display_buses[i].bus_base))) {
1570-
return true;
1575+
could_block = true;
15711576
}
15721577
}
15731578
#endif
1574-
return false;
1579+
return could_block;
15751580
}
15761581

15771582
void supervisor_web_workflow_background(void *data) {

0 commit comments

Comments
 (0)