Rudamentary backlight support

This commit is contained in:
Scott Shawcroft 2019-01-25 18:31:27 -08:00
parent 1a1dbef992
commit 69bc5e189b
No known key found for this signature in database
GPG Key ID: FD0EDC4B6C53CA59
9 changed files with 122 additions and 18 deletions

View File

@ -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) {

View File

@ -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) {

View File

@ -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;
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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);
}
}