diff --git a/ports/atmel-samd/boards/monster_m4sk/mpconfigboard.h b/ports/atmel-samd/boards/monster_m4sk/mpconfigboard.h index 484f3d7b2f..fc77520f5f 100644 --- a/ports/atmel-samd/boards/monster_m4sk/mpconfigboard.h +++ b/ports/atmel-samd/boards/monster_m4sk/mpconfigboard.h @@ -27,5 +27,3 @@ // USB is always used internally so skip the pin objects for it. #define IGNORE_PIN_PA24 1 #define IGNORE_PIN_PA25 1 - -#define CIRCUITPY_FS_NAME "MONSTERM4SK" diff --git a/ports/atmel-samd/common-hal/displayio/ParallelBus.c b/ports/atmel-samd/common-hal/displayio/ParallelBus.c index e2ce9952b4..2479e3b40e 100644 --- a/ports/atmel-samd/common-hal/displayio/ParallelBus.c +++ b/ports/atmel-samd/common-hal/displayio/ParallelBus.c @@ -131,9 +131,9 @@ bool common_hal_displayio_parallelbus_begin_transaction(mp_obj_t obj) { return true; } -void common_hal_displayio_parallelbus_send(mp_obj_t obj, bool command, bool toggle_every_byte, uint8_t *data, uint32_t data_length) { +void common_hal_displayio_parallelbus_send(mp_obj_t obj, display_byte_type_t byte_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length) { displayio_parallelbus_obj_t* self = MP_OBJ_TO_PTR(obj); - common_hal_digitalio_digitalinout_set_value(&self->command, !command); + common_hal_digitalio_digitalinout_set_value(&self->command, byte_type == DISPLAY_DATA); uint32_t* clear_write = (uint32_t*) &self->write_group->OUTCLR.reg; uint32_t* set_write = (uint32_t*) &self->write_group->OUTSET.reg; uint32_t mask = self->write_mask; diff --git a/ports/nrf/common-hal/displayio/ParallelBus.c b/ports/nrf/common-hal/displayio/ParallelBus.c index a8c2b9f73c..be4b28a6e6 100644 --- a/ports/nrf/common-hal/displayio/ParallelBus.c +++ b/ports/nrf/common-hal/displayio/ParallelBus.c @@ -142,9 +142,10 @@ bool common_hal_displayio_parallelbus_begin_transaction(mp_obj_t obj) { return true; } -void common_hal_displayio_parallelbus_send(mp_obj_t obj, bool command, bool toggle_every_byte, uint8_t *data, uint32_t data_length) { +// This ignores chip_select behaviour because data is clocked in by the write line toggling. +void common_hal_displayio_parallelbus_send(mp_obj_t obj, display_byte_type_t byte_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length) { displayio_parallelbus_obj_t* self = MP_OBJ_TO_PTR(obj); - common_hal_digitalio_digitalinout_set_value(&self->command, !command); + common_hal_digitalio_digitalinout_set_value(&self->command, byte_type == DISPLAY_DATA); uint32_t* clear_write = (uint32_t*) &self->write_group->OUTCLR; uint32_t* set_write = (uint32_t*) &self->write_group->OUTSET; uint32_t mask = self->write_mask; diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index 923c02b9ef..c2e2e2d023 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -657,8 +657,4 @@ void run_background_tasks(void); #define CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS 1000 #define CIRCUITPY_BOOT_OUTPUT_FILE "/boot_out.txt" -#ifndef CIRCUITPY_FS_NAME -#define CIRCUITPY_FS_NAME "CIRCUITPY" -#endif - #endif // __INCLUDED_MPCONFIG_CIRCUITPY_H diff --git a/shared-bindings/_stage/__init__.c b/shared-bindings/_stage/__init__.c index 1d970cce4b..d18d306f44 100644 --- a/shared-bindings/_stage/__init__.c +++ b/shared-bindings/_stage/__init__.c @@ -107,7 +107,7 @@ STATIC mp_obj_t stage_render(size_t n_args, const mp_obj_t *args) { area.y2 = y1; displayio_display_core_set_region_to_update(&display->core, display->set_column_command, display->set_row_command, NO_COMMAND, NO_COMMAND, display->data_as_commands, false, &area); - display->core.send(display->core.bus, true, true, &display->write_ram_command, 1); + display->core.send(display->core.bus, DISPLAY_COMMAND, CHIP_SELECT_TOGGLE_EVERY_BYTE, &display->write_ram_command, 1); render_stage(x0, y0, x1, y1, layers, layers_size, buffer, buffer_size, display, scale); displayio_display_core_end_transaction(&display->core); diff --git a/shared-bindings/displayio/Display.c b/shared-bindings/displayio/Display.c index ded4119ca5..1eb1943b82 100644 --- a/shared-bindings/displayio/Display.c +++ b/shared-bindings/displayio/Display.c @@ -218,16 +218,22 @@ STATIC mp_obj_t displayio_display_obj_show(mp_obj_t self_in, mp_obj_t group_in) } MP_DEFINE_CONST_FUN_OBJ_2(displayio_display_show_obj, displayio_display_obj_show); -//| .. method:: refresh(*, target_frames_per_second=None, minimum_frames_per_second=1) +//| .. method:: refresh(*, target_frames_per_second=60, minimum_frames_per_second=1) //| -//| When auto refresh is off, waits for the target frame rate and then refreshes the display. If -//| the call is too late for the given target frame rate, then the refresh returns immediately -//| without updating the screen to hopefully help getting caught up. If the current frame rate -//| is below the minimum frame rate, then an exception will be raised. +//| When auto refresh is off, waits for the target frame rate and then refreshes the display, +//| returning True. If the call has taken too long since the last refresh call for the given +//| target frame rate, then the refresh returns False immediately without updating the screen to +//| hopefully help getting caught up. +//| +//| If the time since the last successful refresh is below the minimum frame rate, then an +//| exception will be raised. Set minimum_frames_per_second to 0 to disable. //| //| When auto refresh is on, updates the display immediately. (The display will also update //| without calls to this.) //| +//| :param int target_frames_per_second: How many times a second `refresh` should be called and the screen updated. +//| :param int minimum_frames_per_second: The minimum number of times the screen should be updated per second. +//| STATIC mp_obj_t displayio_display_obj_refresh(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_target_frames_per_second, ARG_minimum_frames_per_second }; static const mp_arg_t allowed_args[] = { @@ -238,8 +244,12 @@ STATIC mp_obj_t displayio_display_obj_refresh(size_t n_args, const mp_obj_t *pos mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); displayio_display_obj_t *self = native_display(pos_args[0]); - common_hal_displayio_display_refresh(self, 1000 / args[ARG_target_frames_per_second].u_int, 1000 / args[ARG_minimum_frames_per_second].u_int); - return mp_const_none; + uint32_t maximum_ms_per_real_frame = 0xffffffff; + mp_int_t minimum_frames_per_second = args[ARG_minimum_frames_per_second].u_int; + if (minimum_frames_per_second > 0) { + maximum_ms_per_real_frame = 1000 / minimum_frames_per_second; + } + return mp_obj_new_bool(common_hal_displayio_display_refresh(self, 1000 / args[ARG_target_frames_per_second].u_int, maximum_ms_per_real_frame)); } MP_DEFINE_CONST_FUN_OBJ_KW(displayio_display_refresh_obj, 1, displayio_display_obj_refresh); diff --git a/shared-bindings/displayio/Display.h b/shared-bindings/displayio/Display.h index 06c848d0d3..2d7b68c4ed 100644 --- a/shared-bindings/displayio/Display.h +++ b/shared-bindings/displayio/Display.h @@ -51,7 +51,7 @@ bool common_hal_displayio_display_show(displayio_display_obj_t* self, displayio_group_t* root_group); // Times in ms. -void common_hal_displayio_display_refresh(displayio_display_obj_t* self, uint32_t target_frame_time, uint32_t maximum_frame_time); +bool common_hal_displayio_display_refresh(displayio_display_obj_t* self, uint32_t target_ms_per_frame, uint32_t maximum_ms_per_real_frame); bool common_hal_displayio_display_get_auto_refresh(displayio_display_obj_t* self); void common_hal_displayio_display_set_auto_refresh(displayio_display_obj_t* self, bool auto_refresh); diff --git a/shared-bindings/displayio/EPaperDisplay.c b/shared-bindings/displayio/EPaperDisplay.c index 5d0d8ac949..81e06f82f9 100644 --- a/shared-bindings/displayio/EPaperDisplay.c +++ b/shared-bindings/displayio/EPaperDisplay.c @@ -55,7 +55,7 @@ //| //| Create a EPaperDisplay object on the given display bus (`displayio.FourWire` or `displayio.ParallelBus`). //| -//| The ``start_sequence`` and ``stop_sequence`` bitpacked to minimize the ram impact. Every +//| The ``start_sequence`` and ``stop_sequence`` are bitpacked to minimize the ram impact. Every //| command begins with a command byte followed by a byte to determine the parameter count and if //| a delay is need after. When the top bit of the second byte is 1, the next byte will be the //| delay time in milliseconds. The remaining 7 bits are the parameter count excluding any delay diff --git a/shared-bindings/displayio/FourWire.c b/shared-bindings/displayio/FourWire.c index c696233442..51203d4604 100644 --- a/shared-bindings/displayio/FourWire.c +++ b/shared-bindings/displayio/FourWire.c @@ -146,8 +146,12 @@ STATIC mp_obj_t displayio_fourwire_obj_send(size_t n_args, const mp_obj_t *pos_a while (!common_hal_displayio_fourwire_begin_transaction(self)) { RUN_BACKGROUND_TASKS; } - common_hal_displayio_fourwire_send(self, true, args[ARG_toggle_every_byte].u_bool, &command, 1); - common_hal_displayio_fourwire_send(self, false, args[ARG_toggle_every_byte].u_bool, ((uint8_t*) bufinfo.buf), bufinfo.len); + display_chip_select_behavior_t chip_select = CHIP_SELECT_UNTOUCHED; + if (args[ARG_toggle_every_byte].u_bool) { + chip_select = CHIP_SELECT_TOGGLE_EVERY_BYTE; + } + common_hal_displayio_fourwire_send(self, DISPLAY_COMMAND, chip_select, &command, 1); + common_hal_displayio_fourwire_send(self, DISPLAY_DATA, chip_select, ((uint8_t*) bufinfo.buf), bufinfo.len); common_hal_displayio_fourwire_end_transaction(self); return mp_const_none; diff --git a/shared-bindings/displayio/FourWire.h b/shared-bindings/displayio/FourWire.h index 9c71d63cc9..d0935f0639 100644 --- a/shared-bindings/displayio/FourWire.h +++ b/shared-bindings/displayio/FourWire.h @@ -28,6 +28,8 @@ #define MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYBUSIO_FOURWIRE_H #include "shared-module/displayio/FourWire.h" + +#include "shared-bindings/displayio/__init__.h" #include "common-hal/microcontroller/Pin.h" #include "shared-module/displayio/Group.h" @@ -45,7 +47,7 @@ bool common_hal_displayio_fourwire_bus_free(mp_obj_t self); bool common_hal_displayio_fourwire_begin_transaction(mp_obj_t self); -void common_hal_displayio_fourwire_send(mp_obj_t self, bool command, bool toggle_every_byte, uint8_t *data, uint32_t data_length); +void common_hal_displayio_fourwire_send(mp_obj_t self, display_byte_type_t byte_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length); void common_hal_displayio_fourwire_end_transaction(mp_obj_t self); diff --git a/shared-bindings/displayio/I2CDisplay.c b/shared-bindings/displayio/I2CDisplay.c index 4de5e83ef1..4339d182f4 100644 --- a/shared-bindings/displayio/I2CDisplay.c +++ b/shared-bindings/displayio/I2CDisplay.c @@ -131,7 +131,7 @@ STATIC mp_obj_t displayio_i2cdisplay_obj_send(mp_obj_t self, mp_obj_t command_ob uint8_t full_command[bufinfo.len + 1]; full_command[0] = command; memcpy(full_command + 1, ((uint8_t*) bufinfo.buf), bufinfo.len); - common_hal_displayio_i2cdisplay_send(self, true, false, full_command, bufinfo.len + 1); + common_hal_displayio_i2cdisplay_send(self, DISPLAY_COMMAND, CHIP_SELECT_UNTOUCHED, full_command, bufinfo.len + 1); common_hal_displayio_i2cdisplay_end_transaction(self); return mp_const_none; diff --git a/shared-bindings/displayio/I2CDisplay.h b/shared-bindings/displayio/I2CDisplay.h index 683cff383b..bae53c4914 100644 --- a/shared-bindings/displayio/I2CDisplay.h +++ b/shared-bindings/displayio/I2CDisplay.h @@ -28,6 +28,8 @@ #define MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYBUSIO_I2CDISPLAY_H #include "shared-module/displayio/I2CDisplay.h" + +#include "shared-bindings/displayio/__init__.h" #include "common-hal/microcontroller/Pin.h" extern const mp_obj_type_t displayio_i2cdisplay_type; @@ -42,7 +44,7 @@ bool common_hal_displayio_i2cdisplay_bus_free(mp_obj_t self); bool common_hal_displayio_i2cdisplay_begin_transaction(mp_obj_t self); -void common_hal_displayio_i2cdisplay_send(mp_obj_t self, bool command, bool toggle_every_byte, uint8_t *data, uint32_t data_length); +void common_hal_displayio_i2cdisplay_send(mp_obj_t self, display_byte_type_t byte_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length); void common_hal_displayio_i2cdisplay_end_transaction(mp_obj_t self); diff --git a/shared-bindings/displayio/ParallelBus.c b/shared-bindings/displayio/ParallelBus.c index a08c37679b..f7195b9ccb 100644 --- a/shared-bindings/displayio/ParallelBus.c +++ b/shared-bindings/displayio/ParallelBus.c @@ -139,8 +139,8 @@ STATIC mp_obj_t displayio_parallelbus_obj_send(mp_obj_t self, mp_obj_t command_o while (!common_hal_displayio_parallelbus_begin_transaction(self)) { RUN_BACKGROUND_TASKS; } - common_hal_displayio_parallelbus_send(self, true, false, &command, 1); - common_hal_displayio_parallelbus_send(self, false, false, ((uint8_t*) bufinfo.buf), bufinfo.len); + common_hal_displayio_parallelbus_send(self, DISPLAY_COMMAND, CHIP_SELECT_UNTOUCHED, &command, 1); + common_hal_displayio_parallelbus_send(self, DISPLAY_DATA, CHIP_SELECT_UNTOUCHED, ((uint8_t*) bufinfo.buf), bufinfo.len); common_hal_displayio_parallelbus_end_transaction(self); return mp_const_none; diff --git a/shared-bindings/displayio/ParallelBus.h b/shared-bindings/displayio/ParallelBus.h index a0f967332c..be2aef7d44 100644 --- a/shared-bindings/displayio/ParallelBus.h +++ b/shared-bindings/displayio/ParallelBus.h @@ -28,8 +28,9 @@ #define MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYBUSIO_PARALLELBUS_H #include "common-hal/displayio/ParallelBus.h" -#include "common-hal/microcontroller/Pin.h" +#include "common-hal/microcontroller/Pin.h" +#include "shared-bindings/displayio/__init__.h" #include "shared-module/displayio/Group.h" extern const mp_obj_type_t displayio_parallelbus_type; @@ -45,7 +46,7 @@ bool common_hal_displayio_parallelbus_bus_free(mp_obj_t self); bool common_hal_displayio_parallelbus_begin_transaction(mp_obj_t self); -void common_hal_displayio_parallelbus_send(mp_obj_t self, bool command, bool toggle_every_byte, uint8_t *data, uint32_t data_length); +void common_hal_displayio_parallelbus_send(mp_obj_t self, display_byte_type_t byte_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length); void common_hal_displayio_parallelbus_end_transaction(mp_obj_t self); diff --git a/shared-bindings/displayio/__init__.h b/shared-bindings/displayio/__init__.h index 427ddb47dd..122b1fbcbe 100644 --- a/shared-bindings/displayio/__init__.h +++ b/shared-bindings/displayio/__init__.h @@ -27,6 +27,25 @@ #ifndef MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO___INIT___H #define MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO___INIT___H +#include "py/obj.h" + +typedef enum { + DISPLAY_COMMAND, + DISPLAY_DATA +} display_byte_type_t; + + +typedef enum { + CHIP_SELECT_UNTOUCHED, + CHIP_SELECT_TOGGLE_EVERY_BYTE +} display_chip_select_behavior_t; + +typedef bool (*display_bus_bus_reset)(mp_obj_t bus); +typedef bool (*display_bus_bus_free)(mp_obj_t bus); +typedef bool (*display_bus_begin_transaction)(mp_obj_t bus); +typedef void (*display_bus_send)(mp_obj_t bus, display_byte_type_t byte_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length); +typedef void (*display_bus_end_transaction)(mp_obj_t bus); + void common_hal_displayio_release_displays(void); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_DISPLAYIO___INIT___H diff --git a/shared-module/_stage/__init__.c b/shared-module/_stage/__init__.c index bfef165e7b..2c525be87e 100644 --- a/shared-module/_stage/__init__.c +++ b/shared-module/_stage/__init__.c @@ -57,7 +57,7 @@ void render_stage(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, index += 1; // The buffer is full, send it. if (index >= buffer_size) { - display->core.send(display->core.bus, false, false, ((uint8_t*)buffer), + display->core.send(display->core.bus, DISPLAY_DATA, CHIP_SELECT_UNTOUCHED, ((uint8_t*)buffer), buffer_size * 2); index = 0; } @@ -67,6 +67,6 @@ void render_stage(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, } // Send the remaining data. if (index) { - display->core.send(display->core.bus, false, false, ((uint8_t*)buffer), index * 2); + display->core.send(display->core.bus, DISPLAY_DATA, CHIP_SELECT_UNTOUCHED, ((uint8_t*)buffer), index * 2); } } diff --git a/shared-module/displayio/ColorConverter.c b/shared-module/displayio/ColorConverter.c index e0c4ca2869..940aaa1c6d 100644 --- a/shared-module/displayio/ColorConverter.c +++ b/shared-module/displayio/ColorConverter.c @@ -26,6 +26,8 @@ #include "shared-bindings/displayio/ColorConverter.h" +#include "py/misc.h" + void common_hal_displayio_colorconverter_construct(displayio_colorconverter_t* self) { } @@ -45,39 +47,12 @@ uint8_t displayio_colorconverter_compute_luma(uint32_t color_rgb888) { return (r8 * 19) / 255 + (g8 * 182) / 255 + (b8 + 54) / 255; } -void compute_bounds(uint8_t r8, uint8_t g8, uint8_t b8, uint8_t* min, uint8_t* max) { - if (r8 > g8) { - if (b8 > r8) { - *max = b8; - } else { - *max = r8; - } - if (b8 < g8) { - *min = b8; - } else { - *min = g8; - } - } else { - if (b8 > g8) { - *max = b8; - } else { - *max = g8; - } - if (b8 < r8) { - *min = b8; - } else { - *min = r8; - } - } -} - uint8_t displayio_colorconverter_compute_chroma(uint32_t color_rgb888) { uint32_t r8 = (color_rgb888 >> 16); uint32_t g8 = (color_rgb888 >> 8) & 0xff; uint32_t b8 = color_rgb888 & 0xff; - uint8_t max; - uint8_t min; - compute_bounds(r8, g8, b8, &min, &max); + uint8_t max = MAX(r8, MAX(g8, b8)); + uint8_t min = MIN(r8, MIN(g8, b8)); return max - min; } @@ -85,9 +60,8 @@ uint8_t displayio_colorconverter_compute_hue(uint32_t color_rgb888) { uint32_t r8 = (color_rgb888 >> 16); uint32_t g8 = (color_rgb888 >> 8) & 0xff; uint32_t b8 = color_rgb888 & 0xff; - uint8_t max; - uint8_t min; - compute_bounds(r8, g8, b8, &min, &max); + uint8_t max = MAX(r8, MAX(g8, b8)); + uint8_t min = MIN(r8, MIN(g8, b8)); uint8_t c = max - min; if (c == 0) { return 0; diff --git a/shared-module/displayio/Display.c b/shared-module/displayio/Display.c index 109b915074..cb5051bb76 100644 --- a/shared-module/displayio/Display.c +++ b/shared-module/displayio/Display.c @@ -69,7 +69,7 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self, self->data_as_commands = data_as_commands; self->native_frames_per_second = native_frames_per_second; - self->native_frame_time = 1000 / native_frames_per_second; + self->native_ms_per_frame = 1000 / native_frames_per_second; uint32_t i = 0; while (i < init_sequence_len) { @@ -85,10 +85,10 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self, uint8_t full_command[data_size + 1]; full_command[0] = cmd[0]; memcpy(full_command + 1, data, data_size); - self->core.send(self->core.bus, true, true, full_command, data_size + 1); + self->core.send(self->core.bus, DISPLAY_COMMAND, CHIP_SELECT_TOGGLE_EVERY_BYTE, full_command, data_size + 1); } else { - self->core.send(self->core.bus, true, true, cmd, 1); - self->core.send(self->core.bus, false, false, data, data_size); + self->core.send(self->core.bus, DISPLAY_COMMAND, CHIP_SELECT_TOGGLE_EVERY_BYTE, cmd, 1); + self->core.send(self->core.bus, DISPLAY_DATA, CHIP_SELECT_UNTOUCHED, data, data_size); } self->core.end_transaction(self->core.bus); uint16_t delay_length_ms = 10; @@ -168,12 +168,12 @@ bool common_hal_displayio_display_set_brightness(displayio_display_obj_t* self, if (ok) { if (self->data_as_commands) { uint8_t set_brightness[2] = {self->brightness_command, (uint8_t) (0xff * brightness)}; - self->core.send(self->core.bus, true, true, set_brightness, 2); + self->core.send(self->core.bus, DISPLAY_COMMAND, CHIP_SELECT_TOGGLE_EVERY_BYTE, set_brightness, 2); } else { uint8_t command = self->brightness_command; uint8_t hex_brightness = 0xff * brightness; - self->core.send(self->core.bus, true, true, &command, 1); - self->core.send(self->core.bus, false, false, &hex_brightness, 1); + self->core.send(self->core.bus, DISPLAY_COMMAND, CHIP_SELECT_TOGGLE_EVERY_BYTE, &command, 1); + self->core.send(self->core.bus, DISPLAY_DATA, CHIP_SELECT_UNTOUCHED, &hex_brightness, 1); } displayio_display_core_end_transaction(&self->core); } @@ -202,9 +202,9 @@ STATIC const displayio_area_t* _get_refresh_areas(displayio_display_obj_t *self) STATIC void _send_pixels(displayio_display_obj_t* self, uint8_t* pixels, uint32_t length) { if (!self->data_as_commands) { - self->core.send(self->core.bus, true, true, &self->write_ram_command, 1); + self->core.send(self->core.bus, DISPLAY_COMMAND, CHIP_SELECT_TOGGLE_EVERY_BYTE, &self->write_ram_command, 1); } - self->core.send(self->core.bus, false, false, pixels, length); + self->core.send(self->core.bus, DISPLAY_DATA, CHIP_SELECT_UNTOUCHED, pixels, length); } STATIC bool _refresh_area(displayio_display_obj_t* self, const displayio_area_t* area) { @@ -270,12 +270,8 @@ STATIC bool _refresh_area(displayio_display_obj_t* self, const displayio_area_t* subrectangle_size_bytes = displayio_area_size(&subrectangle) / (8 / self->core.colorspace.depth); } - for (uint16_t k = 0; k < mask_length; k++) { - mask[k] = 0x00000000; - } - for (uint16_t k = 0; k < buffer_size; k++) { - buffer[k] = 0x00000000; - } + memset(mask, 0, mask_length * sizeof(uint32_t)); + memset(buffer, 0, buffer_size * sizeof(uint32_t)); displayio_display_core_fill_area(&self->core, &subrectangle, mask, buffer); @@ -313,30 +309,29 @@ uint16_t common_hal_displayio_display_get_rotation(displayio_display_obj_t* self return self->core.rotation; } -void common_hal_displayio_display_refresh(displayio_display_obj_t* self, uint32_t target_frame_time, uint32_t maximum_frame_time) { +bool common_hal_displayio_display_refresh(displayio_display_obj_t* self, uint32_t target_ms_per_frame, uint32_t maximum_ms_per_real_frame) { if (!self->auto_refresh && !self->first_manual_refresh) { uint64_t current_time = ticks_ms; - uint32_t current_frame_time = current_time - self->core.last_refresh; + uint32_t current_ms_since_real_refresh = current_time - self->core.last_refresh; // Test to see if the real frame time is below our minimum. - if (current_frame_time > maximum_frame_time) { + if (current_ms_since_real_refresh > maximum_ms_per_real_frame) { mp_raise_RuntimeError(translate("Below minimum frame rate")); } - uint32_t current_call_time = current_time - self->last_refresh_call; + uint32_t current_ms_since_last_call = current_time - self->last_refresh_call; self->last_refresh_call = current_time; // Skip the actual refresh to help catch up. - if (current_call_time > target_frame_time) { - return; + if (current_ms_since_last_call > target_ms_per_frame) { + return false; } - uint32_t remaining_time = target_frame_time - (current_frame_time % target_frame_time); + uint32_t remaining_time = target_ms_per_frame - (current_ms_since_real_refresh % target_ms_per_frame); // We're ahead of the game so wait until we align with the frame rate. while (ticks_ms - self->last_refresh_call < remaining_time) { - #ifdef MICROPY_VM_HOOK_LOOP - MICROPY_VM_HOOK_LOOP ; - #endif + RUN_BACKGROUND_TASKS; } } self->first_manual_refresh = false; _refresh_display(self); + return true; } bool common_hal_displayio_display_get_auto_refresh(displayio_display_obj_t* self) { @@ -366,7 +361,7 @@ STATIC void _update_backlight(displayio_display_obj_t* self) { void displayio_display_background(displayio_display_obj_t* self) { _update_backlight(self); - if (self->auto_refresh && (ticks_ms - self->core.last_refresh) > self->native_frame_time) { + if (self->auto_refresh && (ticks_ms - self->core.last_refresh) > self->native_ms_per_frame) { _refresh_display(self); } } diff --git a/shared-module/displayio/Display.h b/shared-module/displayio/Display.h index bf2889c6d2..e5fe0a7088 100644 --- a/shared-module/displayio/Display.h +++ b/shared-module/displayio/Display.h @@ -46,7 +46,7 @@ typedef struct { mp_float_t current_brightness; uint16_t brightness_command; uint16_t native_frames_per_second; - uint16_t native_frame_time; + uint16_t native_ms_per_frame; uint8_t set_column_command; uint8_t set_row_command; uint8_t write_ram_command; diff --git a/shared-module/displayio/EPaperDisplay.c b/shared-module/displayio/EPaperDisplay.c index 48143f14ff..38b63df0fd 100644 --- a/shared-module/displayio/EPaperDisplay.c +++ b/shared-module/displayio/EPaperDisplay.c @@ -71,7 +71,7 @@ void common_hal_displayio_epaperdisplay_construct(displayio_epaperdisplay_obj_t* self->busy_state = busy_state; self->refreshing = false; self->milliseconds_per_frame = seconds_per_frame * 1000; - self->always_toggle_chip_select = always_toggle_chip_select; + self->always_toggle_chip_select = always_toggle_chip_select ? CHIP_SELECT_TOGGLE_EVERY_BYTE : CHIP_SELECT_UNTOUCHED; self->start_sequence = start_sequence; self->start_sequence_len = start_sequence_len; @@ -130,9 +130,7 @@ STATIC void wait_for_busy(displayio_epaperdisplay_obj_t* self) { return; } while (common_hal_digitalio_digitalinout_get_value(&self->busy) == self->busy_state) { - #ifdef MICROPY_VM_HOOK_LOOP - MICROPY_VM_HOOK_LOOP - #endif + RUN_BACKGROUND_TASKS; } } @@ -145,8 +143,8 @@ STATIC void send_command_sequence(displayio_epaperdisplay_obj_t* self, bool shou data_size &= ~DELAY; uint8_t *data = cmd + 2; displayio_display_core_begin_transaction(&self->core); - self->core.send(self->core.bus, true, self->always_toggle_chip_select, cmd, 1); - self->core.send(self->core.bus, false, self->always_toggle_chip_select, data, data_size); + self->core.send(self->core.bus, DISPLAY_COMMAND, self->always_toggle_chip_select, cmd, 1); + self->core.send(self->core.bus, DISPLAY_DATA, self->always_toggle_chip_select, data, data_size); displayio_display_core_end_transaction(&self->core); uint16_t delay_length_ms = 0; if (delay) { @@ -187,7 +185,7 @@ uint32_t common_hal_displayio_epaperdisplay_get_time_to_refresh(displayio_epaper void displayio_epaperdisplay_finish_refresh(displayio_epaperdisplay_obj_t* self) { // Actually refresh the display now that all pixel RAM has been updated. displayio_display_core_begin_transaction(&self->core); - self->core.send(self->core.bus, true, self->always_toggle_chip_select, &self->refresh_display_command, 1); + self->core.send(self->core.bus, DISPLAY_COMMAND, self->always_toggle_chip_select, &self->refresh_display_command, 1); displayio_display_core_end_transaction(&self->core); self->refreshing = true; @@ -248,7 +246,7 @@ bool displayio_epaperdisplay_refresh_area(displayio_epaperdisplay_obj_t* self, c write_command = self->write_color_ram_command; } displayio_display_core_begin_transaction(&self->core); - self->core.send(self->core.bus, true, self->always_toggle_chip_select, &write_command, 1); + self->core.send(self->core.bus, DISPLAY_COMMAND, self->always_toggle_chip_select, &write_command, 1); displayio_display_core_end_transaction(&self->core); for (uint16_t j = 0; j < subrectangles; j++) { @@ -266,12 +264,8 @@ bool displayio_epaperdisplay_refresh_area(displayio_epaperdisplay_obj_t* self, c uint16_t subrectangle_size_bytes = displayio_area_size(&subrectangle) / (8 / self->core.colorspace.depth); - for (uint16_t k = 0; k < mask_length; k++) { - mask[k] = 0x00000000; - } - for (uint16_t k = 0; k < buffer_size; k++) { - buffer[k] = 0x00000000; - } + memset(mask, 0, mask_length * sizeof(uint32_t)); + memset(buffer, 0, buffer_size * sizeof(uint32_t)); self->core.colorspace.grayscale = true; if (pass == 1) { @@ -291,7 +285,7 @@ bool displayio_epaperdisplay_refresh_area(displayio_epaperdisplay_obj_t* self, c // Can't acquire display bus; skip the rest of the data. Try next display. return false; } - self->core.send(self->core.bus, false, self->always_toggle_chip_select, (uint8_t*) buffer, subrectangle_size_bytes); + self->core.send(self->core.bus, DISPLAY_DATA, self->always_toggle_chip_select, (uint8_t*) buffer, subrectangle_size_bytes); displayio_display_core_end_transaction(&self->core); // TODO(tannewt): Make refresh displays faster so we don't starve other diff --git a/shared-module/displayio/EPaperDisplay.h b/shared-module/displayio/EPaperDisplay.h index a5d4ec93f9..580171a5f1 100644 --- a/shared-module/displayio/EPaperDisplay.h +++ b/shared-module/displayio/EPaperDisplay.h @@ -56,7 +56,7 @@ typedef struct { bool black_bits_inverted; bool color_bits_inverted; bool refreshing; - bool always_toggle_chip_select; + display_chip_select_behavior_t always_toggle_chip_select; } displayio_epaperdisplay_obj_t; void displayio_epaperdisplay_background(displayio_epaperdisplay_obj_t* self); diff --git a/shared-module/displayio/FourWire.c b/shared-module/displayio/FourWire.c index 7294e9772c..fcc4c1a20a 100644 --- a/shared-module/displayio/FourWire.c +++ b/shared-module/displayio/FourWire.c @@ -33,6 +33,7 @@ #include "shared-bindings/digitalio/DigitalInOut.h" #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/time/__init__.h" +#include "shared-module/displayio/display_core.h" #include "tick.h" @@ -110,10 +111,10 @@ bool common_hal_displayio_fourwire_begin_transaction(mp_obj_t obj) { return true; } -void common_hal_displayio_fourwire_send(mp_obj_t obj, bool command, bool toggle_every_byte, uint8_t *data, uint32_t data_length) { +void common_hal_displayio_fourwire_send(mp_obj_t obj, display_byte_type_t data_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length) { displayio_fourwire_obj_t* self = MP_OBJ_TO_PTR(obj); - common_hal_digitalio_digitalinout_set_value(&self->command, !command); - if (toggle_every_byte) { + common_hal_digitalio_digitalinout_set_value(&self->command, data_type == DISPLAY_DATA); + if (chip_select == CHIP_SELECT_TOGGLE_EVERY_BYTE) { // Toggle chip select after each command byte in case the display driver // IC latches commands based on it. for (size_t i = 0; i < data_length; i++) { diff --git a/shared-module/displayio/I2CDisplay.c b/shared-module/displayio/I2CDisplay.c index 95830ba0e8..87261dca00 100644 --- a/shared-module/displayio/I2CDisplay.c +++ b/shared-module/displayio/I2CDisplay.c @@ -35,6 +35,7 @@ #include "shared-bindings/digitalio/DigitalInOut.h" #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/time/__init__.h" +#include "shared-module/displayio/display_core.h" #include "tick.h" @@ -80,7 +81,7 @@ bool common_hal_displayio_i2cdisplay_reset(mp_obj_t obj) { } common_hal_digitalio_digitalinout_set_value(&self->reset, false); - common_hal_mcu_delay_us(1); + common_hal_mcu_delay_us(4); common_hal_digitalio_digitalinout_set_value(&self->reset, true); return true; } @@ -97,9 +98,9 @@ bool common_hal_displayio_i2cdisplay_begin_transaction(mp_obj_t obj) { return common_hal_displayio_i2cdisplay_bus_free(obj); } -void common_hal_displayio_i2cdisplay_send(mp_obj_t obj, bool command, bool toggle_every_byte, uint8_t *data, uint32_t data_length) { +void common_hal_displayio_i2cdisplay_send(mp_obj_t obj, display_byte_type_t data_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length) { displayio_i2cdisplay_obj_t* self = MP_OBJ_TO_PTR(obj); - if (command) { + if (data_type == DISPLAY_COMMAND) { uint8_t command_bytes[2 * data_length]; for (uint32_t i = 0; i < data_length; i++) { command_bytes[2 * i] = 0x80; diff --git a/shared-module/displayio/display_core.c b/shared-module/displayio/display_core.c index 88878866a5..0f449ea34d 100644 --- a/shared-module/displayio/display_core.c +++ b/shared-module/displayio/display_core.c @@ -184,7 +184,6 @@ void displayio_display_core_end_transaction(displayio_display_core_t* self) { } void displayio_display_core_set_region_to_update(displayio_display_core_t* self, uint8_t column_command, uint8_t row_command, uint16_t set_current_column_command, uint16_t set_current_row_command, bool data_as_commands, bool always_toggle_chip_select, displayio_area_t* area) { - displayio_display_core_begin_transaction(self); uint16_t x1 = area->x1; uint16_t x2 = area->x2; uint16_t y1 = area->y1; @@ -201,13 +200,22 @@ void displayio_display_core_set_region_to_update(displayio_display_core_t* self, } } + display_chip_select_behavior_t chip_select = CHIP_SELECT_UNTOUCHED; + if (always_toggle_chip_select || data_as_commands) { + chip_select = CHIP_SELECT_TOGGLE_EVERY_BYTE; + } + // Set column. + displayio_display_core_begin_transaction(self); uint8_t data[5]; data[0] = column_command; uint8_t data_length = 1; + display_byte_type_t data_type = DISPLAY_DATA; if (!data_as_commands) { - self->send(self->bus, true, false, data, 1); + self->send(self->bus, DISPLAY_COMMAND, CHIP_SELECT_UNTOUCHED, data, 1); data_length = 0; + } else { + data_type = DISPLAY_COMMAND; } if (self->ram_width < 0x100) { data[data_length++] = x1 + self->colstart; @@ -220,21 +228,23 @@ void displayio_display_core_set_region_to_update(displayio_display_core_t* self, data[data_length++] = x2 >> 8; data[data_length++] = x2 & 0xff; } - self->send(self->bus, data_as_commands, data_as_commands, data, data_length); + self->send(self->bus, data_type, chip_select, data, data_length); + displayio_display_core_end_transaction(self); if (set_current_column_command != NO_COMMAND) { uint8_t command = set_current_column_command; - self->send(self->bus, true, always_toggle_chip_select, &command, 1); - self->send(self->bus, false, always_toggle_chip_select, data, data_length / 2); + displayio_display_core_begin_transaction(self); + self->send(self->bus, DISPLAY_COMMAND, chip_select, &command, 1); + self->send(self->bus, DISPLAY_DATA, chip_select, data, data_length / 2); + displayio_display_core_end_transaction(self); } - displayio_display_core_end_transaction(self); - displayio_display_core_begin_transaction(self); // Set row. + displayio_display_core_begin_transaction(self); data[0] = row_command; data_length = 1; if (!data_as_commands) { - self->send(self->bus, true, false, data, 1); + self->send(self->bus, DISPLAY_COMMAND, CHIP_SELECT_UNTOUCHED, data, 1); data_length = 0; } if (self->ram_height < 0x100) { @@ -248,14 +258,16 @@ void displayio_display_core_set_region_to_update(displayio_display_core_t* self, data[data_length++] = y2 >> 8; data[data_length++] = y2 & 0xff; } - self->send(self->bus, data_as_commands, data_as_commands, data, data_length); + self->send(self->bus, data_type, chip_select, data, data_length); + displayio_display_core_end_transaction(self); + if (set_current_row_command != NO_COMMAND) { uint8_t command = set_current_row_command; - self->send(self->bus, true, always_toggle_chip_select, &command, 1); - self->send(self->bus, false, always_toggle_chip_select, data, data_length / 2); + displayio_display_core_begin_transaction(self); + self->send(self->bus, DISPLAY_COMMAND, chip_select, &command, 1); + self->send(self->bus, DISPLAY_DATA, chip_select, data, data_length / 2); + displayio_display_core_end_transaction(self); } - - displayio_display_core_end_transaction(self); } void displayio_display_core_start_refresh(displayio_display_core_t* self) { diff --git a/shared-module/displayio/display_core.h b/shared-module/displayio/display_core.h index b1a412883c..e92fdbc9f1 100644 --- a/shared-module/displayio/display_core.h +++ b/shared-module/displayio/display_core.h @@ -27,18 +27,13 @@ #ifndef MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_DISPLAY_CORE_H #define MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_DISPLAY_CORE_H +#include "shared-bindings/displayio/__init__.h" #include "shared-bindings/displayio/Group.h" #include "shared-module/displayio/area.h" #define NO_COMMAND 0x100 -typedef bool (*display_bus_bus_reset)(mp_obj_t bus); -typedef bool (*display_bus_bus_free)(mp_obj_t bus); -typedef bool (*display_bus_begin_transaction)(mp_obj_t bus); -typedef void (*display_bus_send)(mp_obj_t bus, bool command, bool toggle_every_byte, uint8_t *data, uint32_t data_length); -typedef void (*display_bus_end_transaction)(mp_obj_t bus); - typedef struct { mp_obj_t bus; displayio_group_t *current_group; diff --git a/supervisor/shared/filesystem.c b/supervisor/shared/filesystem.c index 36b30f4622..c50d7f4eeb 100644 --- a/supervisor/shared/filesystem.c +++ b/supervisor/shared/filesystem.c @@ -91,7 +91,7 @@ void filesystem_init(bool create_allowed, bool force_create) { } // set label - f_setlabel(&vfs_fat->fatfs, CIRCUITPY_FS_NAME); + f_setlabel(&vfs_fat->fatfs, "CIRCUITPY"); // inhibit file indexing on MacOS f_mkdir(&vfs_fat->fatfs, "/.fseventsd");