Skip to content

Commit

Permalink
Finished making software rotation available to all bus types
Browse files Browse the repository at this point in the history
The code compiles, I still have yet to test if it actually works.
I also made some changes to the rotation code that should improve performance. Reducing the number of math operations that were being done per pixel.
Decreased memory use when not using software rotation.
  • Loading branch information
kdschlosser committed Dec 23, 2024
1 parent eb818d9 commit 1718aa6
Show file tree
Hide file tree
Showing 16 changed files with 583 additions and 704 deletions.
2 changes: 2 additions & 0 deletions ext_mod/lcd_bus/esp32_include/bus_task.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#ifndef __BUS_TASK_H__
#define __BUS_TASK_H__

#define DEFAULT_STACK_SIZE (5 * 1024)

typedef struct _bus_lock_t {
SemaphoreHandle_t handle;
StaticSemaphore_t buffer;
Expand Down
5 changes: 3 additions & 2 deletions ext_mod/lcd_bus/esp32_include/i2c_bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@

uint32_t buffer_flags;

uint8_t lane_count : 5;
uint8_t trans_done : 1;
uint8_t rgb565_byte_swap : 1;

lcd_panel_io_t panel_io_handle;
esp_lcd_panel_io_i2c_config_t panel_io_config;
i2c_config_t bus_config;
esp_lcd_panel_io_i2c_config_t *panel_io_config;
i2c_config_t *bus_config;
esp_lcd_i2c_bus_handle_t bus_handle;

int host;
Expand Down
5 changes: 3 additions & 2 deletions ext_mod/lcd_bus/esp32_include/i80_bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,14 @@
mp_obj_array_t *view2;
uint32_t buffer_flags;

uint8_t lane_count : 5;
uint8_t trans_done : 1;
uint8_t rgb565_byte_swap : 1;

lcd_panel_io_t panel_io_handle;

esp_lcd_panel_io_i80_config_t panel_io_config;
esp_lcd_i80_bus_config_t bus_config;
esp_lcd_panel_io_i80_config_t *panel_io_config;
esp_lcd_i80_bus_config_t *bus_config;
esp_lcd_i80_bus_handle_t bus_handle;
} mp_lcd_i80_bus_obj_t;

Expand Down
5 changes: 2 additions & 3 deletions ext_mod/lcd_bus/esp32_include/rgb_bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,13 @@

uint32_t buffer_flags;

uint8_t lane_count : 5;
uint8_t trans_done : 1;
uint8_t rgb565_byte_swap : 1;

lcd_panel_io_t panel_io_handle;

esp_lcd_rgb_panel_config_t panel_io_config;
esp_lcd_rgb_timing_t bus_config;

esp_lcd_rgb_panel_config_t *panel_io_config;
esp_lcd_panel_handle_t panel_handle;
uint32_t buffer_size;

Expand Down
39 changes: 15 additions & 24 deletions ext_mod/lcd_bus/esp32_include/rotation.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#include "bus_task.h"
#include "lcd_types.h"

#include "py/misc.h"
// micropy includes
#include "py/obj.h"
#include "py/runtime.h"
#include "mphalport.h"


#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
Expand All @@ -10,16 +13,10 @@
#ifndef __ROTATION_H__
#define __ROTATION_H__

#if LCD_RGB_OPTIMUM_FB_SIZE
typedef struct _rotation_optimum_t {
uint16_t flush_count;
uint8_t sample_count;
uint8_t curr_index;
uint16_t *samples;
bus_lock_t lock;
} rotation_optimum_t;
#endif

#define ROTATION_0 (0)
#define ROTATION_90 (1)
#define ROTATION_180 (2)
#define ROTATION_270 (3)

typedef struct _rotation_task_t {
bus_lock_t lock;
Expand All @@ -41,7 +38,7 @@


typedef struct _rotation_init_err_t {
mp_lcd_err_t code;
int code;
mp_rom_error_text_t msg;
} rotation_init_err_t;

Expand All @@ -63,13 +60,13 @@
int param_cmd[24];
void *param[24];
size_t param_size[24];
bool param_last_cmd[24]
bool param_last_cmd[24];

} rotation_data_t;


typedef mp_lcd_err_t (*init_func_cb_t)(void *self_in);

typedef int (*init_func_cb_t)(void *self_in);
typedef void (*last_update_cb_t)(void *self_in, void *idle_buf);

typedef struct _rotation_t {
rotation_task_t task;
Expand All @@ -79,17 +76,11 @@
int lcd_cmd;

init_func_cb_t init_func;
last_update_cb_t last_update_func;


#if LCD_RGB_OPTIMUM_FB_SIZE
rotation_optimum_t optimum;
#endif
} rotation_t;

void rotation_task_start(void *self_in);
mp_lcd_err_t rotation_set_buffers(void *self_in);

uint32_t rotate(void *src, void *dst, rotation_data_t *data);

int rotation_set_buffers(void *self_in);

#endif
4 changes: 2 additions & 2 deletions ext_mod/lcd_bus/esp32_include/spi_bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@

uint32_t buffer_flags;

uint8_t lane_count : 5;
uint8_t trans_done : 1;
uint8_t rgb565_byte_swap : 1;

lcd_panel_io_t panel_io_handle;
esp_lcd_panel_io_spi_config_t panel_io_config;
spi_bus_config_t bus_config;
esp_lcd_panel_io_spi_config_t *panel_io_config;
esp_lcd_spi_bus_handle_t bus_handle;

spi_host_device_t host;
Expand Down
1 change: 1 addition & 0 deletions ext_mod/lcd_bus/esp32_src/bus_task.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include "bus_task.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
Expand Down
156 changes: 80 additions & 76 deletions ext_mod/lcd_bus/esp32_src/i2c_bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,15 @@


mp_lcd_err_t i2c_del(mp_obj_t obj);
mp_lcd_err_t i2c_init(mp_obj_t obj, uint16_t width, uint16_t height, uint8_t bpp, uint32_t buffer_size, bool rgb565_byte_swap, uint8_t cmd_bits, uint8_t param_bits, bool sw_rotation);
mp_lcd_err_t i2c_get_lane_count(mp_obj_t obj, uint8_t *lane_count);
mp_lcd_err_t i2c_init(mp_obj_t obj, uint16_t width, uint16_t height, uint8_t bpp, uint32_t buffer_size, bool rgb565_byte_swap, uint8_t cmd_bits, uint8_t param_bits, bool sw_rotate);
mp_lcd_err_t i2c_tx_param(mp_obj_t obj, int lcd_cmd, void *param, size_t param_size, bool is_flush, bool last_flush_cmd);


static bool i2c_bus_trans_done_cb(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx)
{
LCD_UNUSED(panel_io);

mp_lcd_spi_bus_obj_t *self = (mp_lcd_spi_bus_obj_t *)user_ctx;
mp_lcd_i2c_bus_obj_t *self = (mp_lcd_i2c_bus_obj_t *)user_ctx;
bus_event_set_from_isr(&self->rotation->task.swap_bufs);
return false;
}
Expand All @@ -40,31 +39,34 @@ static mp_lcd_err_t i2c_rotation_init_func(void *self_in)
{
mp_lcd_i2c_bus_obj_t *self = (mp_lcd_i2c_bus_obj_t *)self_in;

self->panel_io_config.on_color_trans_done = &i2c_bus_trans_done_cb;
self->panel_io_config->on_color_trans_done = &i2c_bus_trans_done_cb;

rotation_t *rotation = self->rotation;
rotation_init_err_t *init_err = &rotation->init_err;
rotation_task_t *task = &rotation->task;
rotation_init_err_t *init_err = &self->rotation->init_err;

init_err->code = i2c_param_config(self->host, self->bus_config);
if (init_err->code != LCD_OK) {
init_err->msg = MP_ERROR_TEXT("%d(i2c_param_config)");
return init_err->code;
}

init_err->code = i2c_param_config(self->host, &self->bus_config);
init_err->code = i2c_driver_install(self->host, I2C_MODE_MASTER, 0, 0, 0);
if (init_err->code != LCD_OK) {
init_err->err_msg = MP_ERROR_TEXT("%d(i2c_param_config)");
bus_lock_release(&task->init_lock);
} else {
init_err->code = i2c_driver_install(self->host, I2C_MODE_MASTER, 0, 0, 0);
if (init_err->code != LCD_OK) {
init_err->err_msg = MP_ERROR_TEXT("%d(i2c_driver_install)");
bus_lock_release(&task->init_lock);
} else {
init_err->code = esp_lcd_new_panel_io_i2c(self->bus_handle , &self->panel_io_config, &self->panel_io_handle.panel_io);
if (init_err->code != LCD_OK) {
init_err->err_msg = MP_ERROR_TEXT("%d(esp_lcd_new_panel_io_i2c)");
bus_lock_release(&task->init_lock);
}
}
init_err->msg = MP_ERROR_TEXT("%d(i2c_driver_install)");
return init_err->code;
}

init_err->code = esp_lcd_new_panel_io_i2c(self->bus_handle , self->panel_io_config, &self->panel_io_handle.panel_io);
if (init_err->code != LCD_OK) {
init_err->msg = MP_ERROR_TEXT("%d(esp_lcd_new_panel_io_i2c)");
return init_err->code;
}

free(self->bus_config);
self->bus_config = NULL;

free(self->panel_io_config);
self->panel_io_config = NULL;

return init_err->code;
}

Expand Down Expand Up @@ -115,28 +117,29 @@ static mp_obj_t mp_lcd_i2c_bus_make_new(const mp_obj_type_t *type, size_t n_args
self->base.type = &mp_lcd_i2c_bus_type;

self->callback = mp_const_none;

self->lane_count = 1;
self->host = args[ARG_host].u_int;
self->bus_handle = (esp_lcd_i2c_bus_handle_t)((uint32_t)self->host);

self->bus_config.mode = I2C_MODE_MASTER;
self->bus_config.sda_io_num = (int)args[ARG_sda].u_int;
self->bus_config.scl_io_num = (int)args[ARG_scl].u_int;
self->bus_config.sda_pullup_en = (bool)args[ARG_sda_pullup].u_bool;
self->bus_config.scl_pullup_en = (bool)args[ARG_scl_pullup].u_bool;
self->bus_config.master.clk_speed = (uint32_t)args[ARG_freq].u_int;
self->bus_config.clk_flags = I2C_SCLK_SRC_FLAG_FOR_NOMAL;

self->panel_io_config.dev_addr = (uint32_t)args[ARG_addr].u_int;
self->panel_io_config.user_ctx = self;
self->panel_io_config.control_phase_bytes = (size_t)args[ARG_control_phase_bytes].u_int;
self->panel_io_config.dc_bit_offset = (unsigned int)args[ARG_dc_bit_offset].u_int;
self->panel_io_config.flags.dc_low_on_data = (unsigned int)args[ARG_dc_low_on_data].u_bool;
self->panel_io_config.flags.disable_control_phase = (unsigned int)args[ARG_disable_control_phase].u_bool;
self->bus_config = (i2c_config_t *)malloc(sizeof(i2c_config_t));
self->bus_config->mode = I2C_MODE_MASTER;
self->bus_config->sda_io_num = (int)args[ARG_sda].u_int;
self->bus_config->scl_io_num = (int)args[ARG_scl].u_int;
self->bus_config->sda_pullup_en = (bool)args[ARG_sda_pullup].u_bool;
self->bus_config->scl_pullup_en = (bool)args[ARG_scl_pullup].u_bool;
self->bus_config->master.clk_speed = (uint32_t)args[ARG_freq].u_int;
self->bus_config->clk_flags = I2C_SCLK_SRC_FLAG_FOR_NOMAL;

self->panel_io_config = (esp_lcd_panel_io_i2c_config_t *)malloc(sizeof(esp_lcd_panel_io_i2c_config_t));
self->panel_io_config->dev_addr = (uint32_t)args[ARG_addr].u_int;
self->panel_io_config->user_ctx = self;
self->panel_io_config->control_phase_bytes = (size_t)args[ARG_control_phase_bytes].u_int;
self->panel_io_config->dc_bit_offset = (unsigned int)args[ARG_dc_bit_offset].u_int;
self->panel_io_config->flags.dc_low_on_data = (unsigned int)args[ARG_dc_low_on_data].u_bool;
self->panel_io_config->flags.disable_control_phase = (unsigned int)args[ARG_disable_control_phase].u_bool;

self->panel_io_handle.del = &i2c_del;
self->panel_io_handle.init = &i2c_init;
self->panel_io_handle.get_lane_count = &i2c_get_lane_count;
self->panel_io_handle.tx_param = &i2c_tx_param;

return MP_OBJ_FROM_PTR(self);
Expand All @@ -160,7 +163,7 @@ mp_lcd_err_t i2c_del(mp_obj_t obj)
}


mp_lcd_err_t i2c_init(mp_obj_t obj, uint16_t width, uint16_t height, uint8_t bpp, uint32_t buffer_size, bool rgb565_byte_swap, uint8_t cmd_bits, uint8_t param_bits, bool sw_rotation)
mp_lcd_err_t i2c_init(mp_obj_t obj, uint16_t width, uint16_t height, uint8_t bpp, uint32_t buffer_size, bool rgb565_byte_swap, uint8_t cmd_bits, uint8_t param_bits, bool sw_rotate)
{
mp_lcd_i2c_bus_obj_t *self = (mp_lcd_i2c_bus_obj_t *)obj;

Expand All @@ -170,55 +173,64 @@ mp_lcd_err_t i2c_init(mp_obj_t obj, uint16_t width, uint16_t height, uint8_t bpp
self->rgb565_byte_swap = false;
}

self->panel_io_config.lcd_cmd_bits = (int)cmd_bits;
self->panel_io_config.lcd_param_bits = (int)param_bits;
self->panel_io_config->lcd_cmd_bits = (int)cmd_bits;
self->panel_io_config->lcd_param_bits = (int)param_bits;

esp_err_t ret;

if (sw_rotation) {
self->rotation = (rotation_t *)malloc(sizeof(rotation_t));
self->rotation->init_func = &i2c_rotation_init_func;
if (sw_rotate) {
self->rotation = (rotation_t *)malloc(sizeof(rotation_t));
self->rotation->init_func = &i2c_rotation_init_func;

rotation_task_start(self);
ret = self->rotation->init_err.code;
ret = rotation_set_buffers(self);
if (ret != LCD_OK) mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("unable to allocate sw rotate fb"));

if (ret != LCD_OK) {
mp_raise_msg_varg(&mp_type_ValueError, self->rotation->init_err.msg, self->rotation->init_err.code);
}
rotation_task_start(self);
ret = self->rotation->init_err.code;

} else {
self->panel_io_config.on_color_trans_done = &bus_trans_done_cb;

ret = i2c_param_config(self->host, &self->bus_config);
if (ret != 0) {
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("%d(i2c_param_config)"), ret);
}

ret = i2c_driver_install(self->host, I2C_MODE_MASTER, 0, 0, 0);
if (ret != 0) {
mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("%d(i2c_driver_install)"), ret);
}

ret = esp_lcd_new_panel_io_i2c(self->bus_handle , &self->panel_io_config, &self->panel_io_handle.panel_io);
if (ret != 0) {
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("%d(esp_lcd_new_panel_io_i2c)"), ret);
}
if (ret != LCD_OK) {
mp_raise_msg_varg(&mp_type_ValueError, self->rotation->init_err.msg, self->rotation->init_err.code);
}
} else {
self->panel_io_config->on_color_trans_done = &bus_trans_done_cb;

ret = i2c_param_config(self->host, self->bus_config);
if (ret != 0) {
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("%d(i2c_param_config)"), ret);
}

ret = i2c_driver_install(self->host, I2C_MODE_MASTER, 0, 0, 0);
if (ret != 0) {
mp_raise_msg_varg(&mp_type_OSError, MP_ERROR_TEXT("%d(i2c_driver_install)"), ret);
}

ret = esp_lcd_new_panel_io_i2c(self->bus_handle , self->panel_io_config, &self->panel_io_handle.panel_io);
if (ret != 0) {
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("%d(esp_lcd_new_panel_io_i2c)"), ret);
}

free(self->bus_config);
self->bus_config = NULL;

free(self->panel_io_config);
self->panel_io_config = NULL;
}

return ret;
}


mp_lcd_err_t i2c_tx_param(mp_obj_t obj, int lcd_cmd, void *param, size_t param_size, bool is_flush, bool last_flush_cmd)
{
mp_lcd_spi_bus_obj_t *self = (mp_lcd_spi_bus_obj_t *)obj;
mp_lcd_i2c_bus_obj_t *self = (mp_lcd_i2c_bus_obj_t *)obj;

mp_lcd_err_t ret;

if (self->rotation == NULL || !is_flush) {
LCD_UNUSED(last_flush_cmd);
ret = esp_lcd_panel_io_tx_param(self->panel_io_handle.panel_io, lcd_cmd, param, param_size);
} else {
bus_lock_acquire(&self->rotation->task.tx_param_lock);
bus_lock_acquire(&self->rotation->task.tx_param_lock, -1);

if (self->rotation->data.tx_param_count == 24) {
bus_lock_release(&self->rotation->task.tx_param_lock);
Expand All @@ -240,14 +252,6 @@ mp_lcd_err_t i2c_tx_param(mp_obj_t obj, int lcd_cmd, void *param, size_t param_s
}


mp_lcd_err_t i2c_get_lane_count(mp_obj_t obj, uint8_t *lane_count)
{
LCD_UNUSED(obj);
*lane_count = 1;
return LCD_OK;
}


MP_DEFINE_CONST_OBJ_TYPE(
mp_lcd_i2c_bus_type,
MP_QSTR_I2CBus,
Expand Down
Loading

0 comments on commit 1718aa6

Please sign in to comment.