summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ports/atmel-samd/boards/pyportal/board.c3
-rw-r--r--ports/atmel-samd/common-hal/pulseio/PWMOut.c47
-rw-r--r--shared-bindings/displayio/Display.c3
-rw-r--r--shared-bindings/displayio/Display.h2
-rw-r--r--shared-bindings/pulseio/PWMOut.c11
-rw-r--r--shared-bindings/pulseio/PWMOut.h14
-rw-r--r--shared-module/displayio/Display.c43
-rw-r--r--shared-module/displayio/Display.h14
-rw-r--r--shared-module/displayio/__init__.c3
9 files changed, 122 insertions, 18 deletions
diff --git a/ports/atmel-samd/boards/pyportal/board.c b/ports/atmel-samd/boards/pyportal/board.c
index 6e5b37dd2..980a28e9b 100644
--- a/ports/atmel-samd/boards/pyportal/board.c
+++ b/ports/atmel-samd/boards/pyportal/board.c
@@ -87,7 +87,8 @@ void board_init(void) {
MIPI_COMMAND_SET_PAGE_ADDRESS, // Set row command
MIPI_COMMAND_WRITE_MEMORY_START, // Write memory command
display_init_sequence,
- sizeof(display_init_sequence));
+ sizeof(display_init_sequence),
+ &pin_PB31);
}
bool board_requests_safe_mode(void) {
diff --git a/ports/atmel-samd/common-hal/pulseio/PWMOut.c b/ports/atmel-samd/common-hal/pulseio/PWMOut.c
index 825bdd181..2740a9e55 100644
--- a/ports/atmel-samd/common-hal/pulseio/PWMOut.c
+++ b/ports/atmel-samd/common-hal/pulseio/PWMOut.c
@@ -58,6 +58,26 @@ uint8_t tcc_channels[3]; // Set by pwmout_reset() to {0xf0, 0xfc, 0xfc} initia
uint8_t tcc_channels[5]; // Set by pwmout_reset() to {0xc0, 0xf0, 0xf8, 0xfc, 0xfc} initially.
#endif
+static uint8_t never_reset_tc_or_tcc[TC_INST_NUM + TCC_INST_NUM];
+
+void common_hal_pulseio_pwmout_never_reset(pulseio_pwmout_obj_t *self) {
+ if (self->timer->is_tc) {
+ never_reset_tc_or_tcc[self->timer->index] += 1;
+ } else {
+ never_reset_tc_or_tcc[TC_INST_NUM + self->timer->index] += 1;
+ }
+
+ never_reset_pin_number(self->pin->number);
+}
+
+void common_hal_pulseio_pwmout_reset_ok(pulseio_pwmout_obj_t *self) {
+ if (self->timer->is_tc) {
+ never_reset_tc_or_tcc[self->timer->index] -= 1;
+ } else {
+ never_reset_tc_or_tcc[TC_INST_NUM + self->timer->index] -= 1;
+ }
+}
+
void pwmout_reset(void) {
// Reset all timers
for (int i = 0; i < TCC_INST_NUM; i++) {
@@ -66,6 +86,9 @@ void pwmout_reset(void) {
}
Tcc *tccs[TCC_INST_NUM] = TCC_INSTS;
for (int i = 0; i < TCC_INST_NUM; i++) {
+ if (never_reset_tc_or_tcc[TC_INST_NUM + i] > 0) {
+ continue;
+ }
// Disable the module before resetting it.
if (tccs[i]->CTRLA.bit.ENABLE == 1) {
tccs[i]->CTRLA.bit.ENABLE = 0;
@@ -81,6 +104,9 @@ void pwmout_reset(void) {
}
Tc *tcs[TC_INST_NUM] = TC_INSTS;
for (int i = 0; i < TC_INST_NUM; i++) {
+ if (never_reset_tc_or_tcc[i] > 0) {
+ continue;
+ }
tcs[i]->COUNT16.CTRLA.bit.SWRST = 1;
while (tcs[i]->COUNT16.CTRLA.bit.SWRST == 1) {
}
@@ -99,11 +125,11 @@ bool channel_ok(const pin_timer_t* t) {
t->is_tc;
}
-void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
- const mcu_pin_obj_t* pin,
- uint16_t duty,
- uint32_t frequency,
- bool variable_frequency) {
+pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
+ const mcu_pin_obj_t* pin,
+ uint16_t duty,
+ uint32_t frequency,
+ bool variable_frequency) {
self->pin = pin;
self->variable_frequency = variable_frequency;
@@ -113,11 +139,11 @@ void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
&& pin->timer[2].index >= TCC_INST_NUM
#endif
) {
- mp_raise_ValueError(translate("Invalid pin"));
+ return PWMOUT_INVALID_PIN;
}
if (frequency == 0 || frequency > 6000000) {
- mp_raise_ValueError(translate("Invalid PWM frequency"));
+ return PWMOUT_INVALID_FREQUENCY;
}
// Figure out which timer we are using.
@@ -184,11 +210,9 @@ void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
if (timer == NULL) {
if (found) {
- mp_raise_ValueError(translate("All timers for this pin are in use"));
- } else {
- mp_raise_RuntimeError(translate("All timers in use"));
+ return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE;
}
- return;
+ return PWMOUT_ALL_TIMERS_IN_USE;
}
uint8_t resolution = 0;
@@ -259,6 +283,7 @@ void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
gpio_set_pin_function(pin->number, GPIO_PIN_FUNCTION_E + mux_position);
common_hal_pulseio_pwmout_set_duty_cycle(self, duty);
+ return PWMOUT_OK;
}
bool common_hal_pulseio_pwmout_deinited(pulseio_pwmout_obj_t* self) {
diff --git a/shared-bindings/displayio/Display.c b/shared-bindings/displayio/Display.c
index 1838228af..398bca166 100644
--- a/shared-bindings/displayio/Display.c
+++ b/shared-bindings/displayio/Display.c
@@ -119,10 +119,11 @@ STATIC mp_obj_t displayio_display_make_new(const mp_obj_type_t *type, size_t n_a
mp_raise_RuntimeError(translate("Too many displays"));
}
self->base.type = &displayio_display_type;
+ // TODO(tannewt): Support backlight pin.
common_hal_displayio_display_construct(self,
display_bus, args[ARG_width].u_int, args[ARG_height].u_int, args[ARG_colstart].u_int, args[ARG_rowstart].u_int,
args[ARG_color_depth].u_int, args[ARG_set_column_command].u_int, args[ARG_set_row_command].u_int,
- args[ARG_write_ram_command].u_int, bufinfo.buf, bufinfo.len);
+ args[ARG_write_ram_command].u_int, bufinfo.buf, bufinfo.len, NULL);
return self;
}
diff --git a/shared-bindings/displayio/Display.h b/shared-bindings/displayio/Display.h
index 4cec66058..181afc941 100644
--- a/shared-bindings/displayio/Display.h
+++ b/shared-bindings/displayio/Display.h
@@ -40,7 +40,7 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self,
mp_obj_t bus, uint16_t width, uint16_t height,
int16_t colstart, int16_t rowstart, uint16_t color_depth,
uint8_t set_column_command, uint8_t set_row_command, uint8_t write_ram_command,
- uint8_t* init_sequence, uint16_t init_sequence_len);
+ uint8_t* init_sequence, uint16_t init_sequence_len, const mcu_pin_obj_t* backlight_pin);
int32_t common_hal_displayio_display_wait_for_frame(displayio_display_obj_t* self);
diff --git a/shared-bindings/pulseio/PWMOut.c b/shared-bindings/pulseio/PWMOut.c
index ed3acd804..bba5fe883 100644
--- a/shared-bindings/pulseio/PWMOut.c
+++ b/shared-bindings/pulseio/PWMOut.c
@@ -108,7 +108,16 @@ STATIC mp_obj_t pulseio_pwmout_make_new(const mp_obj_type_t *type, size_t n_args
// create PWM object from the given pin
pulseio_pwmout_obj_t *self = m_new_obj(pulseio_pwmout_obj_t);
self->base.type = &pulseio_pwmout_type;
- common_hal_pulseio_pwmout_construct(self, pin, duty_cycle, frequency, variable_frequency);
+ pwmout_result_t result = common_hal_pulseio_pwmout_construct(self, pin, duty_cycle, frequency, variable_frequency);
+ if (result == PWMOUT_INVALID_PIN) {
+ mp_raise_ValueError(translate("Invalid pin"));
+ } else if (result == PWMOUT_INVALID_FREQUENCY) {
+ mp_raise_ValueError(translate("Invalid PWM frequency"));
+ } else if (result == PWMOUT_ALL_TIMERS_ON_PIN_IN_USE) {
+ mp_raise_ValueError(translate("All timers for this pin are in use"));
+ } else if (result == PWMOUT_ALL_TIMERS_IN_USE) {
+ mp_raise_RuntimeError(translate("All timers in use"));
+ }
return MP_OBJ_FROM_PTR(self);
}
diff --git a/shared-bindings/pulseio/PWMOut.h b/shared-bindings/pulseio/PWMOut.h
index 0b630816b..c01e0c926 100644
--- a/shared-bindings/pulseio/PWMOut.h
+++ b/shared-bindings/pulseio/PWMOut.h
@@ -32,7 +32,15 @@
extern const mp_obj_type_t pulseio_pwmout_type;
-extern void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
+typedef enum {
+ PWMOUT_OK,
+ PWMOUT_INVALID_PIN,
+ PWMOUT_INVALID_FREQUENCY,
+ PWMOUT_ALL_TIMERS_ON_PIN_IN_USE,
+ PWMOUT_ALL_TIMERS_IN_USE
+} pwmout_result_t;
+
+extern pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
const mcu_pin_obj_t* pin, uint16_t duty, uint32_t frequency,
bool variable_frequency);
extern void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self);
@@ -43,4 +51,8 @@ extern void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self,
extern uint32_t common_hal_pulseio_pwmout_get_frequency(pulseio_pwmout_obj_t* self);
extern bool common_hal_pulseio_pwmout_get_variable_frequency(pulseio_pwmout_obj_t* self);
+// This is used by the supervisor to claim PWMOut devices indefinitely.
+extern void common_hal_pulseio_pwmout_never_reset(pulseio_pwmout_obj_t *self);
+extern void common_hal_pulseio_pwmout_reset_ok(pulseio_pwmout_obj_t *self);
+
#endif // MICROPY_INCLUDED_SHARED_BINDINGS_PULSEIO_PWMOUT_H
diff --git a/shared-module/displayio/Display.c b/shared-module/displayio/Display.c
index fd082c19d..504f130c7 100644
--- a/shared-module/displayio/Display.c
+++ b/shared-module/displayio/Display.c
@@ -29,6 +29,7 @@
#include "py/runtime.h"
#include "shared-bindings/displayio/FourWire.h"
#include "shared-bindings/displayio/ParallelBus.h"
+#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/time/__init__.h"
#include "shared-module/displayio/__init__.h"
#include "supervisor/shared/display.h"
@@ -42,7 +43,8 @@
void common_hal_displayio_display_construct(displayio_display_obj_t* self,
mp_obj_t bus, uint16_t width, uint16_t height, int16_t colstart, int16_t rowstart,
uint16_t color_depth, uint8_t set_column_command, uint8_t set_row_command,
- uint8_t write_ram_command, uint8_t* init_sequence, uint16_t init_sequence_len) {
+ uint8_t write_ram_command, uint8_t* init_sequence, uint16_t init_sequence_len,
+ const mcu_pin_obj_t* backlight_pin) {
self->width = width;
self->height = height;
self->color_depth = color_depth;
@@ -96,6 +98,19 @@ void common_hal_displayio_display_construct(displayio_display_obj_t* self,
// initialization.
self->refresh = true;
self->current_group = &circuitpython_splash;
+
+ if (backlight_pin != NULL && common_hal_mcu_pin_is_free(backlight_pin)) {
+ pwmout_result_t result = common_hal_pulseio_pwmout_construct(&self->backlight_pwm, backlight_pin, 0, 5000, false);
+ if (result != PWMOUT_OK) {
+ self->backlight_inout.base.type = &digitalio_digitalinout_type;
+ common_hal_digitalio_digitalinout_construct(&self->backlight_inout, backlight_pin);
+ never_reset_pin_number(backlight_pin->number);
+ } else {
+ self->backlight_pwm.base.type = &pulseio_pwmout_type;
+ common_hal_pulseio_pwmout_never_reset(&self->backlight_pwm);
+ }
+ }
+ self->auto_brightness = true;
}
void common_hal_displayio_display_show(displayio_display_obj_t* self, displayio_group_t* root_group) {
@@ -158,3 +173,29 @@ bool displayio_display_send_pixels(displayio_display_obj_t* self, uint32_t* pixe
self->send(self->bus, false, (uint8_t*) pixels, length * 4);
return true;
}
+
+void displayio_display_update_backlight(displayio_display_obj_t* self) {
+ if (!self->auto_brightness || self->updating_backlight) {
+ return;
+ }
+ if (ticks_ms - self->last_backlight_refresh < 100) {
+ return;
+ }
+ self->updating_backlight = true;
+ if (self->backlight_pwm.base.type == &pulseio_pwmout_type) {
+ common_hal_pulseio_pwmout_set_duty_cycle(&self->backlight_pwm, 0xffff);
+ } else if (self->backlight_inout.base.type == &digitalio_digitalinout_type) {
+ common_hal_digitalio_digitalinout_set_value(&self->backlight_inout, true);
+ }
+ self->updating_backlight = false;
+ self->last_backlight_refresh = ticks_ms;
+}
+
+void release_display(displayio_display_obj_t* self) {
+ if (self->backlight_pwm.base.type == &pulseio_pwmout_type) {
+ common_hal_pulseio_pwmout_reset_ok(&self->backlight_pwm);
+ common_hal_pulseio_pwmout_deinit(&self->backlight_pwm);
+ } else if (self->backlight_inout.base.type == &digitalio_digitalinout_type) {
+ common_hal_digitalio_digitalinout_deinit(&self->backlight_inout);
+ }
+}
diff --git a/shared-module/displayio/Display.h b/shared-module/displayio/Display.h
index 1f1355d31..0d7393aff 100644
--- a/shared-module/displayio/Display.h
+++ b/shared-module/displayio/Display.h
@@ -27,7 +27,9 @@
#ifndef MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_DISPLAY_H
#define MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_DISPLAY_H
-#include "shared-module/displayio/Group.h"
+#include "shared-bindings/digitalio/DigitalInOut.h"
+#include "shared-bindings/displayio/Group.h"
+#include "shared-bindings/pulseio/PWMOut.h"
typedef bool (*display_bus_begin_transaction)(mp_obj_t bus);
typedef void (*display_bus_send)(mp_obj_t bus, bool command, uint8_t *data, uint32_t data_length);
@@ -50,6 +52,16 @@ typedef struct {
display_bus_begin_transaction begin_transaction;
display_bus_send send;
display_bus_end_transaction end_transaction;
+ union {
+ digitalio_digitalinout_obj_t backlight_inout;
+ pulseio_pwmout_obj_t backlight_pwm;
+ };
+ uint64_t last_backlight_refresh;
+ bool auto_brightness:1;
+ bool updating_backlight:1;
} displayio_display_obj_t;
+void displayio_display_update_backlight(displayio_display_obj_t* self);
+void release_display(displayio_display_obj_t* self);
+
#endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_DISPLAY_H
diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c
index dbfeacc3d..8e4904954 100644
--- a/shared-module/displayio/__init__.c
+++ b/shared-module/displayio/__init__.c
@@ -20,6 +20,7 @@ void displayio_refresh_displays(void) {
continue;
}
displayio_display_obj_t* display = &displays[i].display;
+ displayio_display_update_backlight(display);
if (!displayio_display_frame_queued(display)) {
return;
@@ -82,6 +83,7 @@ void common_hal_displayio_release_displays(void) {
displays[i].fourwire_bus.base.type = &mp_type_NoneType;
}
for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) {
+ release_display(&displays[i].display);
displays[i].display.base.type = &mp_type_NoneType;
}
@@ -117,6 +119,7 @@ void reset_displays(void) {
continue;
}
displayio_display_obj_t* display = &displays[i].display;
+ display->auto_brightness = true;
common_hal_displayio_display_show(display, &circuitpython_splash);
}
}