11// Copyright (c) 2024 - 2025 Kevin G. Schlosser
22
3- // local includes
4- #include "common/lcd_types.h"
5- #include "common/modlcd_bus.h"
6- #include "esp32/i2c_bus.h"
7-
8- // esp-idf includes
9- #include "esp_lcd_panel_io.h"
10- #include "driver/i2c.h"
11-
12- // micropython includes
13- #include "mphalport.h"
143#include "py/obj.h"
154#include "py/runtime.h"
165
17- // stdlib includes
18- #include <string.h>
6+ #include "esp_lcd_panel_io.h"
7+ #include "driver/i2c.h"
198
209
10+ #include "common/lcd_commmon_types.h"
11+ #include "common/modlcd_bus.h"
12+ #include "lcd_types.h"
13+ #include "i2c_bus.h"
2114
2215mp_lcd_err_t i2c_del (mp_obj_t obj );
2316mp_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 );
24- mp_lcd_err_t i2c_get_lane_count (mp_obj_t obj ,uint8_t * lane_count );
2517
2618
27- static uint8_t i2c_bus_count = 0 ;
28- static mp_lcd_i2c_bus_obj_t * * i2c_bus_objs ;
19+ static bool i2c_trans_done_cb (esp_lcd_panel_handle_t panel ,
20+ const esp_lcd_rgb_panel_event_data_t * edata ,void * user_ctx )
21+ {
22+ mp_lcd_i2c_bus_obj_t * self = (mp_lcd_i2c_bus_obj_t * )user_ctx ;
23+
24+ if (self -> trans_done == 0 ) {
25+ if (self -> callback != mp_const_none && mp_obj_is_callable (self -> callback )) {
26+ mp_lcd_flush_ready_cb (self -> callback );
27+ }
28+ self -> trans_done = 1 ;
29+ }
30+
31+ return false;
32+ }
2933
3034
31- void mp_lcd_i2c_bus_deinit_all (void )
35+ static void i2c_tx_param_cb (void * self_in ,int cmd ,uint8_t * params ,size_t params_len )
36+ {
37+ esp_lcd_panel_io_tx_param (self -> panel_io_handle .panel_io ,cmd ,params ,params_len );
38+ }
39+
40+
41+ static bool i2c_init_cb (void * self_in )
3242{
33- // we need to copy the existing array to a new one so the order doesn't
34- // get all mucked up when objects get removed.
35- mp_lcd_i2c_bus_obj_t * objs [i2c_bus_count ];
43+ mp_lcd_i2c_bus_obj_t * self = (mp_lcd_i2c_bus_obj_t * )self_in ;
44+ mp_lcd_sw_rotation_init_t * init = & self -> sw_rot .init ;
45+
46+ init -> err = i2c_param_config (self -> host ,self -> bus_config );
47+ if (init -> err != LCD_OK ) {
48+ init -> err_msg = MP_ERROR_TEXT ("%d(i2c_param_config)" );
49+ return false;
50+ }
3651
37- for (uint8_t i = 0 ;i < i2c_bus_count ;i ++ ) {
38- objs [i ]= i2c_bus_objs [i ];
52+ init -> err = i2c_driver_install (self -> host ,I2C_MODE_MASTER ,0 ,0 ,0 );
53+
54+ if (init -> err != LCD_OK ) {
55+ init -> err_msg = MP_ERROR_TEXT ("%d(i2c_driver_install)" );
56+ return false;
3957 }
4058
41- for (uint8_t i = 0 ;i < i2c_bus_count ;i ++ ) {
42- i2c_del (MP_OBJ_FROM_PTR (objs [i ]));
59+ init -> err = esp_lcd_new_panel_io_i2c (self -> bus_handle ,self -> panel_io_config ,& self -> panel_io_handle .panel_io );
60+
61+ if (init -> err != LCD_OK ) {
62+ init -> err_msg = MP_ERROR_TEXT ("%d(esp_lcd_new_panel_io_i2c)" );
63+ return false;
64+ }
65+
66+ free (self -> panel_io_config );
67+ free (self -> bus_config );
68+ self -> panel_io_config = NULL ;
69+ self -> bus_config = NULL ;
70+
71+ return true;
72+ }
73+
74+
75+ static void i2c_flush_cb (void * self_in ,uint8_t last_update ,int cmd ,uint8_t * idle_fb )
76+ {
77+ LCD_UNUSED (last_update );
78+ mp_lcd_i2c_bus_obj_t * self = (mp_lcd_i2c_bus_obj_t * )self_in ;
79+ mp_lcd_sw_rotation_buffers_t * buffers = & self -> sw_rot .buffers ;
80+
81+
82+ if (idle_fb == buffers -> idle ) {
83+ buffers -> idle = buffers -> active ;
84+ buffers -> active = idle_fb ;
85+ }
86+
87+ mp_lcd_err_t ret = esp_lcd_panel_io_tx_color (self -> panel_io_handle .panel_io ,cmd ,idle_fb ,self -> fb1 -> len );
88+
89+ if (ret != LCD_OK ) {
90+ mp_printf (& mp_plat_print ,"esp_lcd_panel_draw_bitmap error (%d)\n" ,ret );
4391 }
4492}
4593
@@ -120,7 +168,6 @@ static mp_obj_t mp_lcd_i2c_bus_make_new(const mp_obj_type_t *type, size_t n_args
120168
121169self -> panel_io_handle .del = & i2c_del ;
122170self -> panel_io_handle .init = & i2c_init ;
123- self -> panel_io_handle .get_lane_count = & i2c_get_lane_count ;
124171
125172return MP_OBJ_FROM_PTR (self );
126173}
@@ -146,86 +193,30 @@ mp_lcd_err_t i2c_del(mp_obj_t obj)
146193
147194self -> panel_io_handle .panel_io = NULL ;
148195
149- if (self -> view1 != NULL ) {
150- heap_caps_free (self -> view1 -> items );
151- self -> view1 -> items = NULL ;
152- self -> view1 -> len = 0 ;
153- self -> view1 = NULL ;
154- LCD_DEBUG_PRINT ("i2c_free_framebuffer(self, buf=1)\n" )
155- }
156-
157- if (self -> view2 != NULL ) {
158- heap_caps_free (self -> view2 -> items );
159- self -> view2 -> items = NULL ;
160- self -> view2 -> len = 0 ;
161- self -> view2 = NULL ;
162- LCD_DEBUG_PRINT ("i2c_free_framebuffer(self, buf=1)\n" )
163- }
164-
165- uint8_t i = 0 ;
166- for (;i < i2c_bus_count ;i ++ ) {
167- if (i2c_bus_objs [i ]== self ) {
168- i2c_bus_objs [i ]= NULL ;
169- break ;
170- }
171- }
172-
173- for (uint8_t j = i + 1 ;j < i2c_bus_count ;j ++ ) {
174- i2c_bus_objs [j - i + 1 ]= i2c_bus_objs [j ];
175- }
176-
177- i2c_bus_count -- ;
178- i2c_bus_objs = m_realloc (i2c_bus_objs ,i2c_bus_count * sizeof (mp_lcd_i2c_bus_obj_t * ));
179-
180196return ret ;
181197 }else {
182198return LCD_FAIL ;
183199 }
184200}
185201
186202
187- 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 )
203+ mp_lcd_err_t i2c_init (mp_obj_t obj ,uint8_t cmd_bits ,uint8_t param_bits )
188204{
189205mp_lcd_i2c_bus_obj_t * self = (mp_lcd_i2c_bus_obj_t * )obj ;
190206
191- if (bpp == 16 ) {
192- self -> rgb565_byte_swap = rgb565_byte_swap ;
193- }else {
207+ if (self -> sw_rot .data .bytes_per_pixel == 2 ) {
194208self -> rgb565_byte_swap = false;
195- }
196-
209+
197210self -> panel_io_config -> lcd_cmd_bits = (int )cmd_bits ;
198211self -> panel_io_config -> lcd_param_bits = (int )param_bits ;
212+
213+ self -> sw_rot .data .dst_width = 0 ;
214+ self -> sw_rot .data .dst_height = 0 ;
215+ self -> sw_rot .init .cb = & i2c_init_cb ;
216+ self -> sw_rot .flush_cb = & i2c_flush_cb ;
217+ self -> sw_rot .tx_params .cb = & i2c_tx_param_cb ;
199218
200- mp_lcd_err_t ret = i2c_param_config (self -> host ,self -> bus_config );
201- if (ret != 0 ) {
202- mp_raise_msg_varg (& mp_type_ValueError ,MP_ERROR_TEXT ("%d(i2c_param_config)" ),ret );
203- return ret ;
204- }
205-
206- ret = i2c_driver_install (self -> host ,I2C_MODE_MASTER ,0 ,0 ,0 );
207- if (ret != 0 ) {
208- mp_raise_msg_varg (& mp_type_OSError ,MP_ERROR_TEXT ("%d(i2c_driver_install)" ),ret );
209- return ret ;
210- }
211-
212- ret = esp_lcd_new_panel_io_i2c (self -> bus_handle ,self -> panel_io_config ,& self -> panel_io_handle .panel_io );
213-
214- if (ret != 0 ) {
215- mp_raise_msg_varg (& mp_type_ValueError ,MP_ERROR_TEXT ("%d(esp_lcd_new_panel_io_i2c)" ),ret );
216- return ret ;
217- }
218-
219- // add the new bus ONLY after successfull initilization of the bus
220- i2c_bus_count ++ ;
221- i2c_bus_objs = m_realloc (i2c_bus_objs ,i2c_bus_count * sizeof (mp_lcd_i2c_bus_obj_t * ));
222- i2c_bus_objs [i2c_bus_count - 1 ]= self ;
223-
224- free (self -> panel_io_config );
225- free (self -> bus_config );
226- self -> panel_io_config = NULL ;
227- self -> bus_config = NULL ;
228- return ret ;
219+ return LCD_OK ;
229220}
230221
231222