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
4650
4751// The default indicates no primary display
4852static 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
5360displayio_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
6774static 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+
193212void 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
360379void 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
415434primary_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
436455primary_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
457476mp_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 ;
0 commit comments