Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions locale/circuitpython.pot
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,7 @@ msgstr ""
#: ports/analog/common-hal/busio/SPI.c
#: ports/espressif/common-hal/espidf/__init__.c
#: ports/nordic/common-hal/_bleio/__init__.c
#: shared-bindings/epaperdisplay/EPaperDisplay.c
msgid "Invalid state"
msgstr ""

Expand Down Expand Up @@ -1735,8 +1736,10 @@ msgstr ""
#: ports/raspberrypi/common-hal/usb_host/Port.c
#: shared-bindings/digitalio/DigitalInOut.c shared-bindings/emmcio/EMMC.c
#: shared-bindings/i2cioexpander/IOPin.c shared-bindings/microcontroller/Pin.c
#: shared-module/_airlift/__init__.c shared-module/max3421e/Max3421E.c
#: shared-module/usb/core/Device.c shared-module/usb_host_audio/USBIn.c
#: shared-module/_airlift/__init__.c
#: shared-module/epaperdisplay/EPaperDisplay.c
#: shared-module/max3421e/Max3421E.c shared-module/usb/core/Device.c
#: shared-module/usb_host_audio/USBIn.c
msgid "%q in use"
msgstr ""

Expand Down
1 change: 1 addition & 0 deletions ports/atmel-samd/mpconfigport.mk
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ CIRCUITPY_LTO = 1

CIRCUITPY_KEYPAD_DEMUX ?= 0
CIRCUITPY_LVFONTIO ?= 0
CIRCUITPY_EPAPERDISPLAY_FAST ?= 0

CIRCUITPY_DIGITALINOUT_PROTOCOL = 0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ CHIP_VARIANT = RP2040
CHIP_FAMILY = rp2

EXTERNAL_FLASH_DEVICES = "GD25Q64C,W25Q64JVxQ"

CIRCUITPY_EPAPERDISPLAY_LAG = 1
11 changes: 11 additions & 0 deletions py/circuitpy_mpconfig.mk
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,17 @@ CFLAGS += -DCIRCUITPY_QSPIBUS=$(CIRCUITPY_QSPIBUS)
CIRCUITPY_EPAPERDISPLAY ?= $(CIRCUITPY_DISPLAYIO)
CFLAGS += -DCIRCUITPY_EPAPERDISPLAY=$(CIRCUITPY_EPAPERDISPLAY)

# Faster e-paper refreshes: EPaperDisplay's write_previous_ram_command and keep_awake.
CIRCUITPY_EPAPERDISPLAY_FAST ?= $(CIRCUITPY_EPAPERDISPLAY)
CFLAGS += -DCIRCUITPY_EPAPERDISPLAY_FAST=$(CIRCUITPY_EPAPERDISPLAY_FAST)

# Fast e-paper updates with balanced drive: EPaperDisplay's lag_frames and clean().
CIRCUITPY_EPAPERDISPLAY_LAG ?= 0
CFLAGS += -DCIRCUITPY_EPAPERDISPLAY_LAG=$(CIRCUITPY_EPAPERDISPLAY_LAG)
ifeq ($(CIRCUITPY_EPAPERDISPLAY_LAG)$(CIRCUITPY_EPAPERDISPLAY_FAST),10)
$(error CIRCUITPY_EPAPERDISPLAY_LAG needs CIRCUITPY_EPAPERDISPLAY_FAST)
endif

CIRCUITPY_I2CDISPLAYBUS ?= $(CIRCUITPY_DISPLAYIO)
CFLAGS += -DCIRCUITPY_I2CDISPLAYBUS=$(CIRCUITPY_I2CDISPLAYBUS)

Expand Down
6 changes: 6 additions & 0 deletions shared-bindings/displayio/__init__.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,17 @@
//| Once you release a builtin display (one that is initialized automatically, not by user code),
//| the display will remain released even if you restart the CircuitPython VM, for instance by typing ctrl-D.
//| The display is not re-initialized until you do a hard reset or manually initialize it again.
//|
//| If an EPaperDisplay using ``lag_frames`` can't get its bus, this waits up to 30 seconds and then
//| raises `RuntimeError` with every display left as it was, so you can free the bus and call it again.
//| """
//| ...
//|
//|
static mp_obj_t displayio_release_displays(void) {
#if CIRCUITPY_EPAPERDISPLAY_LAG
displayio_prepare_release_displays();
#endif
common_hal_displayio_release_displays();
return mp_const_none;
}
Expand Down
202 changes: 194 additions & 8 deletions shared-bindings/epaperdisplay/EPaperDisplay.c

Large diffs are not rendered by default.

21 changes: 20 additions & 1 deletion shared-bindings/epaperdisplay/EPaperDisplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ typedef struct {
bool black_bits_inverted;
uint16_t write_color_ram_command;
bool color_bits_inverted;
uint16_t write_previous_ram_command;
uint32_t highlight_color;
uint32_t highlight_color2;
const uint8_t *refresh_sequence;
Expand All @@ -51,6 +52,10 @@ typedef struct {
bool spectra6;
bool two_byte_sequence_length;
bool address_little_endian;
bool keep_awake;
uint8_t lag_frames;
const uint8_t *clean_sequence;
uint32_t clean_sequence_len;
} epaperdisplay_construct_args_t;

#define EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS { \
Expand All @@ -75,6 +80,7 @@ typedef struct {
.black_bits_inverted = false, \
.write_color_ram_command = NO_COMMAND, \
.color_bits_inverted = false, \
.write_previous_ram_command = NO_COMMAND, \
.highlight_color = 0x000000, \
.highlight_color2 = 0x000000, \
.refresh_sequence = NULL, \
Expand All @@ -88,14 +94,27 @@ typedef struct {
.acep = false, \
.spectra6 = false, \
.two_byte_sequence_length = false, \
.address_little_endian = false \
.address_little_endian = false, \
.keep_awake = false, \
.lag_frames = 0, \
.clean_sequence = NULL, \
.clean_sequence_len = 0 \
}

void common_hal_epaperdisplay_epaperdisplay_construct(epaperdisplay_epaperdisplay_obj_t *self,
const epaperdisplay_construct_args_t *args);

bool common_hal_epaperdisplay_epaperdisplay_refresh(epaperdisplay_epaperdisplay_obj_t *self);

#if CIRCUITPY_EPAPERDISPLAY_LAG
// Lag drive only. Brings every pixel to white with balanced drive. When full, sends the clean
// sequence and the start sequence. Then wipes each pixel frames toward black and frames toward
// white. Blocks with background tasks running. The next refresh redraws the whole display.
// Doesn't allocate. Holds any interrupt until it ends. Returns false, with any owed drive still
// owed, if the bus can't be had.
bool common_hal_epaperdisplay_epaperdisplay_clean(epaperdisplay_epaperdisplay_obj_t *self, uint8_t frames, bool full);
#endif

mp_obj_t common_hal_epaperdisplay_epaperdisplay_get_root_group(epaperdisplay_epaperdisplay_obj_t *self);
bool common_hal_epaperdisplay_epaperdisplay_set_root_group(epaperdisplay_epaperdisplay_obj_t *self, displayio_group_t *root_group);

Expand Down
15 changes: 15 additions & 0 deletions shared-module/displayio/__init__.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,11 @@ static void common_hal_displayio_release_displays_impl(bool keep_primary) {
#endif
#if CIRCUITPY_EPAPERDISPLAY
} else if (display_type == &epaperdisplay_epaperdisplay_type) {
#if CIRCUITPY_EPAPERDISPLAY_FAST
if (keep_primary) {
epaperdisplay_epaperdisplay_end_held_bus(&displays[i].epaper_display);
}
#endif
release_epaperdisplay(&displays[i].epaper_display);
#endif
#if CIRCUITPY_FRAMEBUFFERIO
Expand Down Expand Up @@ -243,6 +248,16 @@ static void common_hal_displayio_release_displays_impl(bool keep_primary) {
}
}

#if CIRCUITPY_EPAPERDISPLAY_LAG
void displayio_prepare_release_displays(void) {
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
if (displays[i].display_base.type == &epaperdisplay_epaperdisplay_type) {
epaperdisplay_epaperdisplay_prepare_release(&displays[i].epaper_display);
}
}
}
#endif

void common_hal_displayio_release_displays(void) {
common_hal_displayio_release_displays_impl(false);
}
Expand Down
4 changes: 4 additions & 0 deletions shared-module/displayio/__init__.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ extern displayio_group_t circuitpython_splash;

void displayio_background(void);
void reset_displays(void);
#if CIRCUITPY_EPAPERDISPLAY_LAG
// Raises if a display using lag_frames can't finish its drive, before any display is released.
void displayio_prepare_release_displays(void);
#endif
void displayio_gc_collect(void);

primary_display_t *allocate_display(void);
Expand Down
Loading
Loading