def init_gui_stm32(self): import rk043fn48h as lcd import lvstm32 hres = 480 vres = 272 # Register display driver self.tick = lvstm32.lvstm32() lcd.init(w=hres, h=vres) disp_buf1 = lv.disp_buf_t() buf1_1 = lcd.framebuffer(1) buf1_2 = lcd.framebuffer(2) disp_buf1.init(buf1_1, buf1_2, len(buf1_1) // lv.color_t.SIZE) disp_drv = lv.disp_drv_t() disp_drv.init() disp_drv.buffer = disp_buf1 disp_drv.flush_cb = lcd.flush disp_drv.gpu_blend_cb = lcd.gpu_blend disp_drv.gpu_fill_cb = lcd.gpu_fill disp_drv.hor_res = hres disp_drv.ver_res = vres disp_drv.register() # Register touch sensor indev_drv = lv.indev_drv_t() indev_drv.init() indev_drv.type = lv.INDEV_TYPE.POINTER indev_drv.read_cb = lcd.ts_read indev_drv.register()
def init_gui_esp32(self): import lvesp32 import ILI9341 as ili # Initialize ILI9341 display disp = ili.display(miso=5, mosi=18, clk=19, cs=13, dc=12, rst=4, backlight=2) disp.init() # Register display driver disp_buf1 = lv.disp_buf_t() buf1_1 = bytearray(480*10) lv.disp_buf_init(disp_buf1,buf1_1, None, len(buf1_1)//4) disp_drv = lv.disp_drv_t() lv.disp_drv_init(disp_drv) disp_drv.buffer = disp_buf1 disp_drv.flush_cb = disp.flush disp_drv.hor_res = 240 disp_drv.ver_res = 320 lv.disp_drv_register(disp_drv) # Register raw resistive touch driver import rtch touch = rtch.touch(xp = 32, yp = 33, xm = 25, ym = 26, touch_rail = 27, touch_sense = 33) touch.init() indev_drv = lv.indev_drv_t() lv.indev_drv_init(indev_drv) indev_drv.type = lv.INDEV_TYPE.POINTER; indev_drv.read_cb = touch.read; lv.indev_drv_register(indev_drv);
def display_driver_SDL(self): import SDL SDL.init(w=self.width, h=self.height) # Register SDL display driver. disp_buf1 = lv.disp_buf_t() buf1_1 = bytearray(self.width * 10) disp_buf1.init(buf1_1, None, len(buf1_1) // 4) disp_drv = lv.disp_drv_t() disp_drv.init() disp_drv.buffer = disp_buf1 disp_drv.flush_cb = SDL.monitor_flush disp_drv.hor_res = self.width disp_drv.ver_res = self.height disp_drv.register() # Register SDL mouse driver indev_drv = lv.indev_drv_t() indev_drv.init() indev_drv.type = lv.INDEV_TYPE.POINTER indev_drv.read_cb = SDL.mouse_read indev_drv.register() self.type = "SDL" print("Running the SDL lvgl version")
def init_gui_SDL(self): import SDL SDL.init() # Register SDL display driver. disp_buf1 = lv.disp_buf_t() buf1_1 = bytes(480 * 10) disp_buf1.init(buf1_1, None, len(buf1_1) // 4) disp_drv = lv.disp_drv_t() disp_drv.init() disp_drv.buffer = disp_buf1 disp_drv.flush_cb = SDL.monitor_flush disp_drv.hor_res = 480 disp_drv.ver_res = 320 disp_drv.register() # Regsiter SDL mouse driver indev_drv = lv.indev_drv_t() indev_drv.init() indev_drv.type = lv.INDEV_TYPE.POINTER indev_drv.read_cb = SDL.mouse_read indev_drv.register()
def init_disp_drv(self, flush, hor_res, ver_res, buf_size = 0): disp_buf1 = lv.disp_buf_t() if not buf_size: buf_size = (hor_res*ver_res)//4 buf1_1 = bytearray(buf_size) lv.disp_buf_init(disp_buf1,buf1_1, None, len(buf1_1)//4) disp_drv = lv.disp_drv_t() lv.disp_drv_init(disp_drv) disp_drv.buffer = disp_buf1 disp_drv.flush_cb = flush disp_drv.hor_res = hor_res disp_drv.ver_res = ver_res lv.disp_drv_register(disp_drv)
def init_disp_drv(self, flush, hor_res, ver_res, buf_size=0): disp_buf1 = lv.disp_buf_t() if not buf_size: buf_size = (hor_res * ver_res) // lv.color_t.SIZE buf1_1 = bytearray(buf_size) disp_buf1.init(buf1_1, None, len(buf1_1) // lv.color_t.SIZE) disp_drv = lv.disp_drv_t() disp_drv.init() disp_drv.buffer = disp_buf1 disp_drv.flush_cb = flush disp_drv.hor_res = hor_res disp_drv.ver_res = ver_res disp_drv.register()
def init_gui(self): import lvgl as lv import lvgl_helper as lv_h import lcd import time from machine import I2C config_touchscreen_support = True board_m1n = False i2c = I2C(I2C.I2C0, freq=400000, scl=30, sda=31) if not board_m1n: lcd.init() else: lcd.init(type=2, freq=20000000) if config_touchscreen_support: import touchscreen as ts ts.init(i2c) lv.init() disp_buf1 = lv.disp_buf_t() buf1_1 = bytearray(320 * 10) lv.disp_buf_init(disp_buf1, buf1_1, None, len(buf1_1) // 4) disp_drv = lv.disp_drv_t() lv.disp_drv_init(disp_drv) disp_drv.buffer = disp_buf1 disp_drv.flush_cb = lv_h.flush if board_m1n: disp_drv.hor_res = 240 disp_drv.ver_res = 240 else: disp_drv.hor_res = 320 disp_drv.ver_res = 240 lv.disp_drv_register(disp_drv) if config_touchscreen_support: indev_drv = lv.indev_drv_t() lv.indev_drv_init(indev_drv) indev_drv.type = lv.INDEV_TYPE.POINTER indev_drv.read_cb = lv_h.read lv.indev_drv_register(indev_drv) # lv.log_register_print_cb(lv_h.log) lv.log_register_print_cb(lambda level, path, line, msg: print( '%s(%d): %s' % (path, line, msg))) # Create the main screen and load it. self.screen_main = Screen_Main(self) lv.scr_load(self.screen_main)
async def run_display(self): # Initialize the ILI9341 driver # spihost: 1=HSPI 2=VSPI # Workaround note: need to initialize the SPI bus before initializing LittlevGL # SPI bus init was taken out of LittlevGL for streetsense design...should fix this. TODO # SPI bus initialization is done when the SD Card is initialized # (must be called before display initialization) disp = ili.display(spihost=1, miso=19, mosi=23, clk=18, cs=22, dc=21, mhz=25, share=ili.SHARED) disp.init() self.backlight_ctrl.value(0) # note: init() turns on backlight # Register display driver to LittlevGL # ... Start boilerplate magic disp_buf1 = lv.disp_buf_t() buf1_1 = bytearray(320*10) lv.disp_buf_init(disp_buf1,buf1_1, None, len(buf1_1)//4) disp_drv = lv.disp_drv_t() lv.disp_drv_init(disp_drv) disp_drv.buffer = disp_buf1 disp_drv.flush_cb = disp.flush disp_drv.hor_res = 320 disp_drv.ver_res = 240 disp_drv.rotated = 0 lv.disp_drv_register(disp_drv) # ... End boilerplate magic await self.show_welcome_screens() # continually refresh the active screen # detect screen change coming from a button press # detect screen timeout while True: if (self.next_screen != self.active_screen): self.active_screen = self.next_screen self.screen_timeout = False if modes[operating_mode].display == 'timeout': self.timeout_timer.init(period=Display.SCREEN_TIMEOUT_IN_S * 1000, mode=Timer.ONE_SHOT, callback=self.screen_timeout_callback) elif (self.screen_timeout == True): self.next_screen = len(self.screens) - 1 # display the active screen await self.screens[self.active_screen]() await asyncio.sleep(Display.SCREEN_REFRESH_IN_S)
def _register_disp_drv(self): # Init buffer self._disp_buf = lv.disp_buf_t() self._buf_1 = bytearray(DISP_BUF_SIZE) self._buf_2 = bytearray(DISP_BUF_SIZE) self._disp_drv = lv.disp_drv_t() lv.disp_buf_init(self._disp_buf, self._buf_1, self._buf_2, DISP_BUF_SIZE // 4) # Register display driver lv.disp_drv_init(self._disp_drv) self._disp_drv.buffer = self._disp_buf self._disp_drv.flush_cb = self._tft.flush self._disp_drv.hor_res = 480 self._disp_drv.ver_res = 320 self._disp = lv.disp_drv_register(self._disp_drv) return
def __init__(self): disp_buf1 = lv.disp_buf_t() buf1_1 = bytearray(390 * 32) lv.disp_buf_init(disp_buf1, buf1_1, None, len(buf1_1) // 4) disp_drv = lv.disp_drv_t() lv.disp_drv_init(disp_drv) disp_drv.buffer = disp_buf1 disp_drv.flush_cb = display.flush disp_drv.hor_res = 390 disp_drv.ver_res = 390 lv.disp_drv_register(disp_drv) touchscreen.init() indev_drv = lv.indev_drv_t() lv.indev_drv_init(indev_drv) indev_drv.type = lv.INDEV_TYPE.POINTER indev_drv.read_cb = touchscreen.touchscreen_read lv.indev_drv_register(indev_drv)
def init(): """ GUI initialization function. Should be called once in the very beginning. """ # init the gui library lv.init() # init the hardware library SDL.init() # Register SDL display driver disp_buf1 = lv.disp_buf_t() buf1_1 = bytearray(HOR_RES*10) lv.disp_buf_init(disp_buf1,buf1_1, None, len(buf1_1)//4) disp_drv = lv.disp_drv_t() lv.disp_drv_init(disp_drv) disp_drv.buffer = disp_buf1 disp_drv.flush_cb = SDL.monitor_flush disp_drv.hor_res = HOR_RES disp_drv.ver_res = VER_RES lv.disp_drv_register(disp_drv) # Regsiter SDL mouse driver indev_drv = lv.indev_drv_t() lv.indev_drv_init(indev_drv) indev_drv.type = lv.INDEV_TYPE.POINTER; indev_drv.read_cb = SDL.mouse_read; lv.indev_drv_register(indev_drv); # Set up material theme # First argument (210) is a hue - theme color shift, # Second - default font to use. Builtin: roboto_16, roboto_28 th = lv.theme_material_init(210, lv.font_roboto_22) lv.theme_set_current(th) # Create a screen and load it # To access active screen use lv.scr_act() scr = lv.obj() lv.scr_load(scr) # Initialize the styles styles["title"] = lv.style_t() # Title style - just a default style with larger font lv.style_copy(styles["title"], lv.style_plain) styles["title"].text.font = lv.font_roboto_28
def screen_init(): sda_pin = machine.Pin(23) scl_pin = machine.Pin(32) i2c = machine.I2C(id=1, scl=scl_pin, sda=sda_pin, speed=400000) ts.init(i2c) tft.init(tft.ST7789, width=240, invrot=3, rot=1, bgr=False, height=240, miso=2, mosi=19, clk=18, cs=5, dc=27, speed=40000000, color_bits=tft.COLOR_BITS16, backl_pin=12, backl_on=1) tft.clear(tft.RED) time.sleep(1) tft.clear(tft.GREEN) time.sleep(1) tft.clear(tft.BLUE) time.sleep(1) lv.init() disp_buf1 = lv.disp_buf_t() buf1_1 = bytes(240 * 10) lv.disp_buf_init(disp_buf1, buf1_1, None, len(buf1_1) // 4) disp_drv = lv.disp_drv_t() lv.disp_drv_init(disp_drv) disp_drv.buffer = disp_buf1 disp_drv.flush_cb = lv_h.flush disp_drv.hor_res = 240 disp_drv.ver_res = 240 lv.disp_drv_register(disp_drv) indev_drv = lv.indev_drv_t() lv.indev_drv_init(indev_drv) indev_drv.type = lv.INDEV_TYPE.POINTER indev_drv.read_cb = lv_h.read lv.indev_drv_register(indev_drv) scr = lv.obj() btn = lv.btn(scr) btn.align(lv.scr_act(), lv.ALIGN.CENTER, 0, 0) label = lv.label(btn) label.set_text("Button") lv.scr_load(scr)
def init(autoupdate=True): import lvgl as lv import SDL HOR_RES = 480 VER_RES = 800 """ GUI initialization function. Should be called once in the very beginning. """ # init the gui library lv.init() # init the hardware library SDL.init() # Register SDL display driver disp_buf1 = lv.disp_buf_t() buf1_1 = bytearray(HOR_RES * 10) lv.disp_buf_init(disp_buf1, buf1_1, None, len(buf1_1) // 4) disp_drv = lv.disp_drv_t() lv.disp_drv_init(disp_drv) disp_drv.buffer = disp_buf1 disp_drv.flush_cb = SDL.monitor_flush disp_drv.hor_res = HOR_RES disp_drv.ver_res = VER_RES lv.disp_drv_register(disp_drv) # Regsiter SDL mouse driver indev_drv = lv.indev_drv_t() lv.indev_drv_init(indev_drv) indev_drv.type = lv.INDEV_TYPE.POINTER indev_drv.read_cb = SDL.mouse_read lv.indev_drv_register(indev_drv) scr = lv.obj() lv.scr_load(scr) if autoupdate: import SDL SDL.enable_autoupdate()
def __init__(self, miso=5, mosi=18, clk=19, cs=13, dc=12, rst=4, power=14, backlight=15, backlight_on=0, power_on=0, spihost=esp.HSPI_HOST, mhz=40, factor=4, hybrid=True, width=240, height=320, colormode=COLOR_MODE_BGR, rot=PORTRAIT, invert=False, double_buffer=True): # Make sure Micropython was built such that color won't require processing before DMA if lv.color_t.SIZE != 2: raise RuntimeError( 'ili9341 micropython driver requires defining LV_COLOR_DEPTH=16' ) if colormode == COLOR_MODE_BGR and not hasattr(lv.color_t().ch, 'green_l'): raise RuntimeError( 'ili9341 BGR color mode requires defining LV_COLOR_16_SWAP=1') # Initializations self.width = width self.height = height self.miso = miso self.mosi = mosi self.clk = clk self.cs = cs self.dc = dc self.rst = rst self.power = power self.backlight = backlight self.backlight_on = backlight_on self.power_on = power_on self.spihost = spihost self.mhz = mhz self.factor = factor self.hybrid = hybrid self.buf_size = (self.width * self.height * lv.color_t.SIZE) // factor self.init_cmds = [ { 'cmd': 0xCF, 'data': bytes([0x00, 0x83, 0X30]) }, { 'cmd': 0xED, 'data': bytes([0x64, 0x03, 0X12, 0X81]) }, { 'cmd': 0xE8, 'data': bytes([0x85, 0x01, 0x79]) }, { 'cmd': 0xCB, 'data': bytes([0x39, 0x2C, 0x00, 0x34, 0x02]) }, { 'cmd': 0xF7, 'data': bytes([0x20]) }, { 'cmd': 0xEA, 'data': bytes([0x00, 0x00]) }, { 'cmd': 0xC0, 'data': bytes([0x26]) }, # Power control { 'cmd': 0xC1, 'data': bytes([0x11]) }, # Power control { 'cmd': 0xC5, 'data': bytes([0x35, 0x3E]) }, # VCOM control { 'cmd': 0xC7, 'data': bytes([0xBE]) }, # VCOM control { 'cmd': 0x36, 'data': bytes([rot | colormode]) }, # Memory Access Control { 'cmd': 0x3A, 'data': bytes([0x55]) }, # Pixel Format Set { 'cmd': 0xB1, 'data': bytes([0x00, 0x1B]) }, { 'cmd': 0xF2, 'data': bytes([0x08]) }, { 'cmd': 0x26, 'data': bytes([0x01]) }, { 'cmd': 0xE0, 'data': bytes([ 0x1F, 0x1A, 0x18, 0x0A, 0x0F, 0x06, 0x45, 0X87, 0x32, 0x0A, 0x07, 0x02, 0x07, 0x05, 0x00 ]) }, { 'cmd': 0XE1, 'data': bytes([ 0x00, 0x25, 0x27, 0x05, 0x10, 0x09, 0x3A, 0x78, 0x4D, 0x05, 0x18, 0x0D, 0x38, 0x3A, 0x1F ]) }, { 'cmd': 0x2A, 'data': bytes([0x00, 0x00, 0x00, 0xEF]) }, { 'cmd': 0x2B, 'data': bytes([0x00, 0x00, 0x01, 0x3f]) }, { 'cmd': 0x2C, 'data': bytes([0]) }, { 'cmd': 0xB7, 'data': bytes([0x07]) }, { 'cmd': 0xB6, 'data': bytes([0x0A, 0x82, 0x27, 0x00]) }, { 'cmd': 0x11, 'data': bytes([0]), 'delay': 100 }, { 'cmd': 0x29, 'data': bytes([0]), 'delay': 100 } ] if invert: self.init_cmds.append({'cmd': 0x21}) self.init() # Register display driver self.buf1 = esp.heap_caps_malloc(self.buf_size, esp.MALLOC_CAP.DMA) self.buf2 = esp.heap_caps_malloc( self.buf_size, esp.MALLOC_CAP.DMA) if double_buffer else None if self.buf1 and self.buf2: print("Double buffer") elif self.buf1: print("Single buffer") else: raise RuntimeError( "Not enough DMA-able memory to allocate display buffer") self.disp_buf = lv.disp_buf_t() self.disp_drv = lv.disp_drv_t() lv.disp_buf_init(self.disp_buf, self.buf1, self.buf2, self.buf_size // lv.color_t.SIZE) lv.disp_drv_init(self.disp_drv) self.disp_drv.user_data = {'dc': self.dc, 'spi': self.spi} self.disp_drv.buffer = self.disp_buf self.disp_drv.flush_cb = esp.ili9341_flush if self.hybrid and hasattr( esp, 'ili9341_flush') else self.flush self.disp_drv.monitor_cb = self.monitor self.disp_drv.hor_res = self.width self.disp_drv.ver_res = self.height lv.disp_drv_register(self.disp_drv)
# MIT license; Copyright (c) 2019 David Madl import lvgl as lv import lcd_v3 # should start with this, otherwise there may not be enough memory left frame_buf = bytearray(240 * 240 + 240 + 9 * 4) def my_flush_cb(disp_drv, area, color_p): lcd_v3.write(frame_buf) lcd_v3.pwm_pins_toggle( ) # note: original application toggles the display with 60 Hz (= stable frame rate?) lv.disp_flush_ready(disp_drv) # Display buffer disp_buf = lv.disp_buf_t() lv.disp_buf_init(disp_buf, frame_buf, None, 240 * 240) # Display driver disp_drv = lv.disp_drv_t() lv.disp_drv_init(disp_drv) disp_drv.buffer = disp_buf disp_drv.flush_cb = my_flush_cb disp_drv.hor_res = 240 disp_drv.ver_res = 240 disp = lv.disp_drv_register(disp_drv) lcd_v3.pwm_pins_init()
def __init__(self, miso=5, mosi=18, clk=19, cs=13, dc=12, rst=4, power=14, backlight=15, backlight_on=0, power_on=0, spihost=esp.HSPI_HOST, mhz=40, factor=4, hybrid=True, width=240, height=320, colormode=COLOR_MODE_BGR, rot=PORTRAIT, invert=False, double_buffer=True, half_duplex=True, display_type=0, asynchronous=False, initialize=True): # Initializations self.asynchronous = asynchronous self.initialize = initialize self.width = width self.height = height self.miso = miso self.mosi = mosi self.clk = clk self.cs = cs self.dc = dc self.rst = rst self.power = power self.backlight = backlight self.backlight_on = backlight_on self.power_on = power_on self.spihost = spihost self.mhz = mhz self.factor = factor self.hybrid = hybrid self.half_duplex = half_duplex self.buf_size = (self.width * self.height * lv.color_t.SIZE) // factor if invert: self.init_cmds.append({'cmd': 0x21}) # Register display driver self.buf1 = esp.heap_caps_malloc(self.buf_size, esp.MALLOC_CAP.DMA) self.buf2 = esp.heap_caps_malloc( self.buf_size, esp.MALLOC_CAP.DMA) if double_buffer else None if self.buf1 and self.buf2: print("Double buffer") elif self.buf1: print("Single buffer") else: raise RuntimeError( "Not enough DMA-able memory to allocate display buffer") self.disp_buf = lv.disp_buf_t() self.disp_drv = lv.disp_drv_t() self.disp_buf.init(self.buf1, self.buf2, self.buf_size // lv.color_t.SIZE) self.disp_drv.init() self.disp_spi_init() self.disp_drv.user_data = { 'dc': self.dc, 'spi': self.spi, 'dt': self.display_type } self.disp_drv.buffer = self.disp_buf self.disp_drv.flush_cb = esp.ili9xxx_flush if hybrid and hasattr( esp, 'ili9xxx_flush') else self.flush self.disp_drv.monitor_cb = self.monitor self.disp_drv.hor_res = self.width self.disp_drv.ver_res = self.height if self.initialize: self.init()
class ili9341: width = const(240) height = const(320) ###################################################### disp_buf = lv.disp_buf_t() disp_drv = lv.disp_drv_t() # "power" and "backlight" are reversed logic! 0 means ON. def __init__(self, miso=5, mosi=18, clk=19, cs=13, dc=12, rst=4, power=14, backlight=15, spihost=esp.enum.HSPI_HOST, mhz=40, factor=4, hybrid=True): # Make sure Micropython was built such that color won't require processing before DMA if lv.color_t.SIZE != 2: raise RuntimeError( 'ili9341 micropython driver requires defining LV_COLOR_DEPTH=16' ) if not hasattr(lv.color_t().ch, 'green_l'): raise RuntimeError( 'ili9341 micropython driver requires defining LV_COLOR_16_SWAP=1' ) # Initializations self.miso = miso self.mosi = mosi self.clk = clk self.cs = cs self.dc = dc self.rst = rst self.power = power self.backlight = backlight self.spihost = spihost self.mhz = mhz self.factor = factor self.hybrid = hybrid self.buf_size = (self.width * self.height * lv.color_t.SIZE) // factor self.init() # Register display driver self.buf1 = esp.heap_caps_malloc(self.buf_size, esp.CAP.DMA) self.buf2 = esp.heap_caps_malloc(self.buf_size, esp.CAP.DMA) if self.buf1 and self.buf2: print("Double buffer") elif self.buf1: print("Single buffer") else: raise RuntimeError( "Not enough DMA-able memory to allocate display buffer") lv.disp_buf_init(self.disp_buf, self.buf1, self.buf2, self.buf_size // lv.color_t.SIZE) lv.disp_drv_init(self.disp_drv) self.disp_drv.user_data = {'dc': self.dc, 'spi': self.spi} self.disp_drv.buffer = self.disp_buf self.disp_drv.flush_cb = esp.ili9341_flush if self.hybrid and hasattr( esp, 'ili9341_flush') else self.flush self.disp_drv.monitor_cb = self.monitor self.disp_drv.hor_res = self.width self.disp_drv.ver_res = self.height lv.disp_drv_register(self.disp_drv) ###################################################### init_cmds = [ { 'cmd': 0xCF, 'data': bytes([0x00, 0x83, 0X30]) }, { 'cmd': 0xED, 'data': bytes([0x64, 0x03, 0X12, 0X81]) }, { 'cmd': 0xE8, 'data': bytes([0x85, 0x01, 0x79]) }, { 'cmd': 0xCB, 'data': bytes([0x39, 0x2C, 0x00, 0x34, 0x02]) }, { 'cmd': 0xF7, 'data': bytes([0x20]) }, { 'cmd': 0xEA, 'data': bytes([0x00, 0x00]) }, { 'cmd': 0xC0, 'data': bytes([0x26]) }, # Power control { 'cmd': 0xC1, 'data': bytes([0x11]) }, # Power control { 'cmd': 0xC5, 'data': bytes([0x35, 0x3E]) }, # VCOM control { 'cmd': 0xC7, 'data': bytes([0xBE]) }, # VCOM control { 'cmd': 0x36, 'data': bytes([0x48]) }, # Memory Access Control { 'cmd': 0x3A, 'data': bytes([0x55]) }, # Pixel Format Set { 'cmd': 0xB1, 'data': bytes([0x00, 0x1B]) }, { 'cmd': 0xF2, 'data': bytes([0x08]) }, { 'cmd': 0x26, 'data': bytes([0x01]) }, { 'cmd': 0xE0, 'data': bytes([ 0x1F, 0x1A, 0x18, 0x0A, 0x0F, 0x06, 0x45, 0X87, 0x32, 0x0A, 0x07, 0x02, 0x07, 0x05, 0x00 ]) }, { 'cmd': 0XE1, 'data': bytes([ 0x00, 0x25, 0x27, 0x05, 0x10, 0x09, 0x3A, 0x78, 0x4D, 0x05, 0x18, 0x0D, 0x38, 0x3A, 0x1F ]) }, { 'cmd': 0x2A, 'data': bytes([0x00, 0x00, 0x00, 0xEF]) }, { 'cmd': 0x2B, 'data': bytes([0x00, 0x00, 0x01, 0x3f]) }, { 'cmd': 0x2C, 'data': bytes([0]) }, { 'cmd': 0xB7, 'data': bytes([0x07]) }, { 'cmd': 0xB6, 'data': bytes([0x0A, 0x82, 0x27, 0x00]) }, { 'cmd': 0x11, 'data': bytes([0]), 'delay': 100 }, { 'cmd': 0x29, 'data': bytes([0]), 'delay': 100 } ] ###################################################### def disp_spi_init(self): buscfg = esp.spi_bus_config_t({ "miso_io_num": self.miso, "mosi_io_num": self.mosi, "sclk_io_num": self.clk, "quadwp_io_num": -1, "quadhd_io_num": -1, "max_transfer_sz": self.buf_size, }) devcfg = esp.spi_device_interface_config_t({ "clock_speed_hz": self.mhz * 1000 * 1000, # Clock out at DISP_SPI_MHZ MHz "mode": 0, # SPI mode 0 "spics_io_num": self.cs, # CS pin "queue_size": 2, "flags": esp.ESP.HALF_DUPLEX, "duty_cycle_pos": 128, }) if self.hybrid and hasattr(esp, 'ili9341_post_cb_isr'): devcfg.pre_cb = None devcfg.post_cb = esp.ili9341_post_cb_isr else: devcfg.pre_cb = esp.spi_pre_cb_isr devcfg.post_cb = esp.spi_post_cb_isr esp.gpio_pad_select_gpio(self.miso) esp.gpio_pad_select_gpio(self.mosi) esp.gpio_pad_select_gpio(self.clk) esp.gpio_set_direction(self.miso, esp.GPIO_MODE.INPUT) esp.gpio_set_pull_mode(self.miso, esp.GPIO.PULLUP_ONLY) esp.gpio_set_direction(self.mosi, esp.GPIO_MODE.OUTPUT) esp.gpio_set_direction(self.clk, esp.GPIO_MODE.OUTPUT) esp.gpio_pad_select_gpio(self.cs) # Initialize the SPI bus ret = esp.spi_bus_initialize(self.spihost, buscfg, 1) if ret != 0: raise RuntimeError("Failed initializing SPI bus") # Attach the LCD to the SPI bus ptr_to_spi = esp.C_Pointer() ret = esp.spi_bus_add_device(self.spihost, devcfg, ptr_to_spi) if ret != 0: raise RuntimeError("Failed adding SPI device") self.spi = ptr_to_spi.ptr_val self.bytes_transmitted = 0 completed_spi_transaction = esp.spi_transaction_t() cast_spi_transaction_instance = esp.spi_transaction_t.cast_instance def post_isr(arg): reported_transmitted = self.bytes_transmitted if reported_transmitted > 0: print('- Completed DMA of %d bytes (mem_free=0x%X)' % (reported_transmitted, gc.mem_free())) self.bytes_transmitted -= reported_transmitted # Called in ISR context! def flush_isr(spi_transaction_ptr): lv.disp_flush_ready(self.disp_drv) # esp.spi_device_release_bus(self.spi) esp.get_ccount(self.end_time_ptr) # cast_spi_transaction_instance(completed_spi_transaction, spi_transaction_ptr) # self.bytes_transmitted += completed_spi_transaction.length # try: # micropython.schedule(post_isr, None) # except RuntimeError: # pass self.spi_callbacks = esp.spi_transaction_set_cb(None, flush_isr) ###################################################### trans = esp.spi_transaction_t() # .cast( # esp.heap_caps_malloc( # esp.spi_transaction_t.SIZE, esp.CAP.DMA)) def spi_send(self, data): self.trans.length = len( data) * 8 # Length is in bytes, transaction length is in bits. self.trans.tx_buffer = data # data should be allocated as DMA-able memory self.trans.user = None esp.spi_device_polling_transmit(self.spi, self.trans) def spi_send_dma(self, data): self.trans.length = len( data) * 8 # Length is in bytes, transaction length is in bits. self.trans.tx_buffer = data # data should be allocated as DMA-able memory self.trans.user = self.spi_callbacks esp.spi_device_queue_trans(self.spi, self.trans, -1) ###################################################### ###################################################### trans_buffer_len = const(16) trans_buffer = esp.heap_caps_malloc(trans_buffer_len, esp.CAP.DMA) cmd_trans_data = trans_buffer.__dereference__(1) word_trans_data = trans_buffer.__dereference__(4) def send_cmd(self, cmd): esp.gpio_set_level(self.dc, 0) # Command mode self.cmd_trans_data[0] = cmd self.spi_send(self.cmd_trans_data) def send_data(self, data): esp.gpio_set_level(self.dc, 1) # Data mode if len(data) > self.trans_buffer_len: raise RuntimeError('Data too long, please use DMA!') trans_data = self.trans_buffer.__dereference__(len(data)) trans_data[:] = data[:] self.spi_send(trans_data) def send_trans_word(self): esp.gpio_set_level(self.dc, 1) # Data mode self.spi_send(self.word_trans_data) def send_data_dma(self, data): # data should be allocated as DMA-able memory esp.gpio_set_level(self.dc, 1) # Data mode self.spi_send_dma(data) ###################################################### def init(self): self.disp_spi_init() # Initialize non-SPI GPIOs esp.gpio_pad_select_gpio(self.dc) esp.gpio_pad_select_gpio(self.rst) if self.backlight != -1: esp.gpio_pad_select_gpio(self.backlight) if self.power != -1: esp.gpio_pad_select_gpio(self.power) esp.gpio_set_direction(self.dc, esp.GPIO_MODE.OUTPUT) esp.gpio_set_direction(self.rst, esp.GPIO_MODE.OUTPUT) if self.backlight != -1: esp.gpio_set_direction(self.backlight, esp.GPIO_MODE.OUTPUT) if self.power != -1: esp.gpio_set_direction(self.power, esp.GPIO_MODE.OUTPUT) # Power the display if self.power != -1: esp.gpio_set_level(self.power, 0) esp.task_delay_ms(100) # Reset the display esp.gpio_set_level(self.rst, 0) esp.task_delay_ms(100) esp.gpio_set_level(self.rst, 1) esp.task_delay_ms(100) # Send all the commands for cmd in self.init_cmds: self.send_cmd(cmd['cmd']) self.send_data(cmd['data']) if 'delay' in cmd: esp.task_delay_ms(cmd['delay']) print("ILI9341 initialization completed") # Enable backlight if self.backlight != -1: print("Enable backlight") esp.gpio_set_level(self.backlight, 0) ###################################################### start_time_ptr = esp.C_Pointer() end_time_ptr = esp.C_Pointer() flush_acc_setup_cycles = 0 flush_acc_dma_cycles = 0 def flush(self, disp_drv, area, color_p): if self.end_time_ptr.int_val and self.end_time_ptr.int_val > self.start_time_ptr.int_val: self.flush_acc_dma_cycles += self.end_time_ptr.int_val - self.start_time_ptr.int_val esp.get_ccount(self.start_time_ptr) # esp.spi_device_acquire_bus(self.spi, esp.ESP.MAX_DELAY) # Column addresses self.send_cmd(0x2A) self.word_trans_data[0] = (area.x1 >> 8) & 0xFF self.word_trans_data[1] = area.x1 & 0xFF self.word_trans_data[2] = (area.x2 >> 8) & 0xFF self.word_trans_data[3] = area.x2 & 0xFF self.send_trans_word() # Page addresses self.send_cmd(0x2B) self.word_trans_data[0] = (area.y1 >> 8) & 0xFF self.word_trans_data[1] = area.y1 & 0xFF self.word_trans_data[2] = (area.y2 >> 8) & 0xFF self.word_trans_data[3] = area.y2 & 0xFF self.send_trans_word() # Memory write by DMA, disp_flush_ready when finished self.send_cmd(0x2C) size = (area.x2 - area.x1 + 1) * (area.y2 - area.y1 + 1) data_view = color_p.__dereference__(size * lv.color_t.SIZE) esp.get_ccount(self.end_time_ptr) if self.end_time_ptr.int_val > self.start_time_ptr.int_val: self.flush_acc_setup_cycles += self.end_time_ptr.int_val - self.start_time_ptr.int_val esp.get_ccount(self.start_time_ptr) self.send_data_dma(data_view) ###################################################### monitor_acc_time = 0 monitor_acc_px = 0 monitor_count = 0 cycles_in_ms = esp.esp_clk_cpu_freq() // 1000 def monitor(self, disp_drv, time, px): self.monitor_acc_time += time self.monitor_acc_px += px self.monitor_count += 1 def stat(self): if self.monitor_count == 0: return None time = self.monitor_acc_time // self.monitor_count setup = self.flush_acc_setup_cycles // (self.monitor_count * self.cycles_in_ms) dma = self.flush_acc_dma_cycles // (self.monitor_count * self.cycles_in_ms) px = self.monitor_acc_px // self.monitor_count self.monitor_acc_time = 0 self.monitor_acc_px = 0 self.monitor_count = 0 self.flush_acc_setup_cycles = 0 self.flush_acc_dma_cycles = 0 return time, setup, dma, px
def __init__( self, m5stack, miso=5, mosi=18, clk=19, cs=13, dc=12, backlight_on=0, power_on=0, spihost=esp.HSPI_HOST, mhz=40, factor=4, hybrid=True, width=320, height=240, colormode=COLOR_MODE_BGR, rot=LANDSCAPE, invert=False, double_buffer=True, half_duplex=True, display_type=0, debug=False, ): # Initializations self.debug = debug self.width = width self.height = height self.m5stack = m5stack self.miso = miso self.mosi = mosi self.clk = clk self.cs = cs self.dc = dc self.backlight_on = backlight_on self.power_on = power_on self.spihost = spihost self.mhz = mhz self.factor = factor self.hybrid = hybrid self.half_duplex = half_duplex self.buf_size = (self.width * self.height * lv.color_t.SIZE) // factor if invert: self.init_cmds.append({"cmd": 0x21}) self.init() # Register display driver self.buf1 = esp.heap_caps_malloc(self.buf_size, esp.MALLOC_CAP.DMA) self.buf2 = (esp.heap_caps_malloc(self.buf_size, esp.MALLOC_CAP.DMA) if double_buffer else None) if self.buf1 and self.buf2: if self.debug: print("Double buffer") elif self.buf1: if self.debug: print("Single buffer") else: raise RuntimeError( "Not enough DMA-able memory to allocate display buffer") self.disp_buf = lv.disp_buf_t() self.disp_drv = lv.disp_drv_t() self.disp_buf.init(self.buf1, self.buf2, self.buf_size // lv.color_t.SIZE) self.disp_drv.init() self.disp_drv.user_data = { "dc": self.dc, "spi": self.spi, "dt": self.display_type } self.disp_drv.buffer = self.disp_buf self.disp_drv.flush_cb = (esp.ili9xxx_flush if hybrid and hasattr(esp, "ili9xxx_flush") else self.flush) self.disp_drv.monitor_cb = self.monitor self.disp_drv.hor_res = self.width self.disp_drv.ver_res = self.height self.disp_drv.register()
class ili9341: width = const(240) height = const(320) ###################################################### disp_buf = lv.disp_buf_t() disp_drv = lv.disp_drv_t() def __init__(self, miso=5, mosi=18, clk=19, cs=13, dc=12, rst=4, backlight=2, spihost=esp.enum.HSPI_HOST, mhz=40, factor=5): # Make sure Micropython was built such that color won't require processing before DMA if lv.color_t.SIZE != 2: raise RuntimeError( 'ili9341 micropython driver requires defining LV_COLOR_DEPTH=16' ) if not hasattr(lv.color_t().ch, 'green_l'): raise RuntimeError( 'ili9341 micropython driver requires defining LV_COLOR_16_SWAP=1' ) # Initializations self.miso = miso self.mosi = mosi self.clk = clk self.cs = cs self.dc = dc self.rst = rst self.backlight = backlight self.spihost = spihost self.mhz = mhz self.init() # Register display driver buf_size = (self.width * self.height * lv.color_t.SIZE) // factor lv.disp_buf_init(self.disp_buf, bytearray(buf_size), bytearray(buf_size), buf_size // lv.color_t.SIZE) lv.disp_drv_init(self.disp_drv) self.disp_drv.buffer = self.disp_buf self.disp_drv.flush_cb = self.flush self.disp_drv.monitor_cb = self.monitor self.disp_drv.hor_res = self.width self.disp_drv.ver_res = self.height lv.disp_drv_register(self.disp_drv) ###################################################### init_cmds = [ { 'cmd': 0xCF, 'data': bytes([0x00, 0x83, 0X30]) }, { 'cmd': 0xED, 'data': bytes([0x64, 0x03, 0X12, 0X81]) }, { 'cmd': 0xE8, 'data': bytes([0x85, 0x01, 0x79]) }, { 'cmd': 0xCB, 'data': bytes([0x39, 0x2C, 0x00, 0x34, 0x02]) }, { 'cmd': 0xF7, 'data': bytes([0x20]) }, { 'cmd': 0xEA, 'data': bytes([0x00, 0x00]) }, { 'cmd': 0xC0, 'data': bytes([0x26]) }, # Power control { 'cmd': 0xC1, 'data': bytes([0x11]) }, # Power control { 'cmd': 0xC5, 'data': bytes([0x35, 0x3E]) }, # VCOM control { 'cmd': 0xC7, 'data': bytes([0xBE]) }, # VCOM control { 'cmd': 0x36, 'data': bytes([0x48]) }, # Memory Access Control { 'cmd': 0x3A, 'data': bytes([0x55]) }, # Pixel Format Set { 'cmd': 0xB1, 'data': bytes([0x00, 0x1B]) }, { 'cmd': 0xF2, 'data': bytes([0x08]) }, { 'cmd': 0x26, 'data': bytes([0x01]) }, { 'cmd': 0xE0, 'data': bytes([ 0x1F, 0x1A, 0x18, 0x0A, 0x0F, 0x06, 0x45, 0X87, 0x32, 0x0A, 0x07, 0x02, 0x07, 0x05, 0x00 ]) }, { 'cmd': 0XE1, 'data': bytes([ 0x00, 0x25, 0x27, 0x05, 0x10, 0x09, 0x3A, 0x78, 0x4D, 0x05, 0x18, 0x0D, 0x38, 0x3A, 0x1F ]) }, { 'cmd': 0x2A, 'data': bytes([0x00, 0x00, 0x00, 0xEF]) }, { 'cmd': 0x2B, 'data': bytes([0x00, 0x00, 0x01, 0x3f]) }, { 'cmd': 0x2C, 'data': bytes([0]) }, { 'cmd': 0xB7, 'data': bytes([0x07]) }, { 'cmd': 0xB6, 'data': bytes([0x0A, 0x82, 0x27, 0x00]) }, { 'cmd': 0x11, 'data': bytes([0]), 'delay': 100 }, { 'cmd': 0x29, 'data': bytes([0]), 'delay': 100 } ] ###################################################### def disp_spi_init(self): buscfg = esp.spi_bus_config_t({ "miso_io_num": self.miso, "mosi_io_num": self.mosi, "sclk_io_num": self.clk, "quadwp_io_num": -1, "quadhd_io_num": -1, "max_transfer_sz": 128 * 1024, }) devcfg = esp.spi_device_interface_config_t({ "clock_speed_hz": self.mhz * 1000 * 1000, # Clock out at DISP_SPI_MHZ MHz "mode": 0, # SPI mode 0 "spics_io_num": self.cs, # CS pin "queue_size": 2, "pre_cb": esp.spi_pre_cb_isr, "post_cb": esp.spi_post_cb_isr, "flags": 1 << 4, # SPI_DEVICE_HALFDUPLEX "duty_cycle_pos": 128, }) esp.gpio_pad_select_gpio(self.miso) esp.gpio_pad_select_gpio(self.mosi) esp.gpio_pad_select_gpio(self.clk) esp.gpio_set_direction(self.miso, esp.GPIO_MODE.INPUT) esp.gpio_set_pull_mode(self.miso, esp.GPIO.PULLUP_ONLY) esp.gpio_set_direction(self.mosi, esp.GPIO_MODE.OUTPUT) esp.gpio_set_direction(self.clk, esp.GPIO_MODE.OUTPUT) esp.gpio_pad_select_gpio(self.cs) # Initialize the SPI bus ret = esp.spi_bus_initialize(self.spihost, buscfg, 1) if ret != 0: raise RuntimeError("Failed initializing SPI bus") # Attach the LCD to the SPI bus ptr_to_spi = esp.C_Pointer() ret = esp.spi_bus_add_device(self.spihost, devcfg, ptr_to_spi) if ret != 0: raise RuntimeError("Failed adding SPI device") self.spi = ptr_to_spi.ptr_val self.bytes_transmitted = 0 completed_spi_transaction = esp.spi_transaction_t() cast_spi_transaction_instance = esp.spi_transaction_t.cast_instance def post_isr(arg): reported_transmitted = self.bytes_transmitted if reported_transmitted > 0: print('- Completed DMA of %d bytes (mem_free=0x%X)' % (reported_transmitted, gc.mem_free())) self.bytes_transmitted -= reported_transmitted # Called in ISR context! def flush_isr(spi_transaction_ptr): lv.disp_flush_ready(self.disp_drv) # cast_spi_transaction_instance(completed_spi_transaction, spi_transaction_ptr) # self.bytes_transmitted += completed_spi_transaction.length # try: # micropython.schedule(post_isr, None) # except RuntimeError: # pass self.spi_callbacks = esp.spi_transaction_set_cb(None, flush_isr) ###################################################### trans = esp.spi_transaction_t() trans_res = esp.spi_transaction_t() def disp_spi_send(self, data, dma=False): if len(data) == 0: return # no need to send anything self.trans.length = len( data) * 8 # Length is in bytes, transaction length is in bits. self.trans.tx_buffer = data if dma: self.trans.user = self.spi_callbacks esp.spi_device_queue_trans(self.spi, self.trans, -1) else: self.trans.user = None esp.spi_device_polling_transmit(self.spi, self.trans) ###################################################### cmd_data = bytearray(1) def send_cmd(self, cmd): self.cmd_data[0] = cmd esp.gpio_set_level(self.dc, 0) # Command mode self.disp_spi_send(self.cmd_data) def send_data(self, data, dma=False): esp.gpio_set_level(self.dc, 1) # Data mode self.disp_spi_send(data, dma=dma) ###################################################### def init(self): self.disp_spi_init() esp.gpio_pad_select_gpio(self.dc) # Initialize non-SPI GPIOs esp.gpio_set_direction(self.dc, esp.GPIO_MODE.OUTPUT) esp.gpio_set_direction(self.rst, esp.GPIO_MODE.OUTPUT) if self.backlight != -1: esp.gpio_set_direction(self.backlight, esp.GPIO_MODE.OUTPUT) # Reset the display esp.gpio_set_level(self.rst, 0) esp.task_delay_ms(100) esp.gpio_set_level(self.rst, 1) esp.task_delay_ms(100) # Send all the commands for cmd in self.init_cmds: self.send_cmd(cmd['cmd']) self.send_data(cmd['data']) if 'delay' in cmd: esp.task_delay_ms(cmd['delay']) print("ILI9341 initialization completed") # Enable backlight if self.backlight != -1: print("Enable backlight") esp.gpio_set_level(self.backlight, 1) ###################################################### flush_data = bytearray(4) def flush(self, disp_drv, area, color_p): # Column addresses self.send_cmd(0x2A) self.flush_data[0] = (area.x1 >> 8) & 0xFF self.flush_data[1] = area.x1 & 0xFF self.flush_data[2] = (area.x2 >> 8) & 0xFF self.flush_data[3] = area.x2 & 0xFF self.send_data(self.flush_data) # Page addresses self.send_cmd(0x2B) self.flush_data[0] = (area.y1 >> 8) & 0xFF self.flush_data[1] = area.y1 & 0xFF self.flush_data[2] = (area.y2 >> 8) & 0xFF self.flush_data[3] = area.y2 & 0xFF self.send_data(self.flush_data) # Memory write by DMA, disp_flush_ready when finished self.send_cmd(0x2C) size = (area.x2 - area.x1 + 1) * (area.y2 - area.y1 + 1) data_view = color_p.__dereference__(size * lv.color_t.SIZE) self.send_data(data_view, dma=True) ###################################################### monitor_acc_time = 0 monitor_acc_px = 0 monitor_count = 0 def monitor(self, disp_drv, time, px): self.monitor_acc_time += time self.monitor_acc_px += px self.monitor_count += 1 def stat(self): if self.monitor_count == 0: return None time = self.monitor_acc_time // self.monitor_count px = self.monitor_acc_px // self.monitor_count self.monitor_acc_time = 0 self.monitor_acc_px = 0 self.monitor_count = 0 return time, px
if DEBUG: print(TOUCH.state, TOUCH.points) data.point = lv.point_t({'x': TOUCH.points[1][0], 'y': TOUCH.points[1][1]}) data.state = lv.INDEV_STATE.PR if TOUCH.state == 1 else lv.INDEV_STATE.REL return False if config_touchscreen_support: i2c = I2C(I2C.I2C0, freq=1000*1000, scl=24, sda=27) # 24 27) devices = i2c.scan() print("devs", devices) # devs 0 [16, 38, 52, 56] TouchLow.config(i2c) TOUCH = Touch(480, 320, 200) lv.init() disp_buf1 = lv.disp_buf_t() buf1_1 = bytearray(320*10) lv.disp_buf_init(disp_buf1,buf1_1, None, len(buf1_1)//4) disp_drv = lv.disp_drv_t() lv.disp_drv_init(disp_drv) disp_drv.buffer = disp_buf1 disp_drv.flush_cb = lv_h.flush if board_m1n: disp_drv.hor_res = 240 disp_drv.ver_res = 240 else: disp_drv.hor_res = 480 disp_drv.ver_res = 320 lv.disp_drv_register(disp_drv)
class ili9341: width = const(240) height = const(320) ###################################################### disp_buf1 = lv.disp_buf_t() disp_drv = lv.disp_drv_t() def __init__(self, miso=5, mosi=18, clk=19, cs=13, dc=12, rst=4, backlight=2, spihost=esp.enum.HSPI_HOST, mhz=40, factor=10): # Make sure Micropython was built such that color won't require processing before DMA if lv.color_t.SIZE != 2: raise RuntimeError( 'ili9341 micropython driver requires defining LV_COLOR_DEPTH=16' ) if not hasattr(lv.color_t().ch, 'green_l'): raise RuntimeError( 'ili9341 micropython driver requires defining LV_COLOR_16_SWAP=1' ) # Initializations self.buf1_1 = bytearray( (self.width * self.height * lv.color_t.SIZE) // factor) self.miso = miso self.mosi = mosi self.clk = clk self.cs = cs self.dc = dc self.rst = rst self.backlight = backlight self.spihost = spihost self.mhz = mhz self.init() # Register display driver lv.disp_buf_init(self.disp_buf1, self.buf1_1, None, len(self.buf1_1) // lv.color_t.SIZE) lv.disp_drv_init(self.disp_drv) self.disp_drv.buffer = self.disp_buf1 self.disp_drv.flush_cb = self.flush self.disp_drv.hor_res = self.width self.disp_drv.ver_res = self.height lv.disp_drv_register(self.disp_drv) ###################################################### init_cmds = [ { 'cmd': 0xCF, 'data': bytearray([0x00, 0x83, 0X30]) }, { 'cmd': 0xED, 'data': bytearray([0x64, 0x03, 0X12, 0X81]) }, { 'cmd': 0xE8, 'data': bytearray([0x85, 0x01, 0x79]) }, { 'cmd': 0xCB, 'data': bytearray([0x39, 0x2C, 0x00, 0x34, 0x02]) }, { 'cmd': 0xF7, 'data': bytearray([0x20]) }, { 'cmd': 0xEA, 'data': bytearray([0x00, 0x00]) }, { 'cmd': 0xC0, 'data': bytearray([0x26]) }, # Power control { 'cmd': 0xC1, 'data': bytearray([0x11]) }, # Power control { 'cmd': 0xC5, 'data': bytearray([0x35, 0x3E]) }, # VCOM control { 'cmd': 0xC7, 'data': bytearray([0xBE]) }, # VCOM control { 'cmd': 0x36, 'data': bytearray([0x48]) }, # Memory Access Control { 'cmd': 0x3A, 'data': bytearray([0x55]) }, # Pixel Format Set { 'cmd': 0xB1, 'data': bytearray([0x00, 0x1B]) }, { 'cmd': 0xF2, 'data': bytearray([0x08]) }, { 'cmd': 0x26, 'data': bytearray([0x01]) }, { 'cmd': 0xE0, 'data': bytearray([ 0x1F, 0x1A, 0x18, 0x0A, 0x0F, 0x06, 0x45, 0X87, 0x32, 0x0A, 0x07, 0x02, 0x07, 0x05, 0x00 ]) }, { 'cmd': 0XE1, 'data': bytearray([ 0x00, 0x25, 0x27, 0x05, 0x10, 0x09, 0x3A, 0x78, 0x4D, 0x05, 0x18, 0x0D, 0x38, 0x3A, 0x1F ]) }, { 'cmd': 0x2A, 'data': bytearray([0x00, 0x00, 0x00, 0xEF]) }, { 'cmd': 0x2B, 'data': bytearray([0x00, 0x00, 0x01, 0x3f]) }, { 'cmd': 0x2C, 'data': bytearray([0]) }, { 'cmd': 0xB7, 'data': bytearray([0x07]) }, { 'cmd': 0xB6, 'data': bytearray([0x0A, 0x82, 0x27, 0x00]) }, { 'cmd': 0x11, 'data': bytearray([0]), 'delay': 100 }, { 'cmd': 0x29, 'data': bytearray([0]), 'delay': 100 } ] ###################################################### def disp_spi_init(self): buscfg = esp.spi_bus_config_t({ "miso_io_num": self.miso, "mosi_io_num": self.mosi, "sclk_io_num": self.clk, "quadwp_io_num": -1, "quadhd_io_num": -1, "max_transfer_sz": 128 * 1024, }) devcfg = esp.spi_device_interface_config_t({ "clock_speed_hz": self.mhz * 1000 * 1000, # Clock out at DISP_SPI_MHZ MHz "mode": 0, # SPI mode 0 "spics_io_num": self.cs, # CS pin "queue_size": 1, "pre_cb": None, "post_cb": None, "flags": 1 << 4, # SPI_DEVICE_HALFDUPLEX "duty_cycle_pos": 128, }) esp.gpio_pad_select_gpio(self.miso) esp.gpio_pad_select_gpio(self.mosi) esp.gpio_pad_select_gpio(self.clk) esp.gpio_set_direction(self.miso, esp.GPIO_MODE.INPUT) esp.gpio_set_pull_mode(self.miso, esp.GPIO.PULLUP_ONLY) esp.gpio_set_direction(self.mosi, esp.GPIO_MODE.OUTPUT) esp.gpio_set_direction(self.clk, esp.GPIO_MODE.OUTPUT) esp.gpio_pad_select_gpio(self.cs) # Initialize the SPI bus ret = esp.spi_bus_initialize(self.spihost, buscfg, 1) if ret != 0: raise RuntimeError("Failed initializing SPI bus") # Attach the LCD to the SPI bus ptr_to_spi = esp.C_Pointer() ret = esp.spi_bus_add_device(self.spihost, devcfg, ptr_to_spi) if ret != 0: raise RuntimeError("Failed adding SPI device") self.spi = ptr_to_spi.ptr_val ###################################################### trans = esp.spi_transaction_t() trans_res = esp.spi_transaction_t() def disp_spi_send(self, data): if len(data) == 0: return # no need to send anything self.trans.length = len( data) * 8 # Length is in bytes, transaction length is in bits. self.trans.tx_buffer = data esp.spi_device_queue_trans(self.spi, self.trans, -1) esp.spi_device_get_trans_result(self.spi, self.trans_res, -1) ###################################################### cmd_data = bytearray(1) def send_cmd(self, cmd): self.cmd_data[0] = cmd esp.gpio_set_level(self.dc, 0) # Command mode self.disp_spi_send(self.cmd_data) def send_data(self, data): esp.gpio_set_level(self.dc, 1) # Data mode self.disp_spi_send(data) ###################################################### def init(self): self.disp_spi_init() esp.gpio_pad_select_gpio(self.dc) # Initialize non-SPI GPIOs esp.gpio_set_direction(self.dc, esp.GPIO_MODE.OUTPUT) esp.gpio_set_direction(self.rst, esp.GPIO_MODE.OUTPUT) if self.backlight != -1: esp.gpio_set_direction(self.backlight, esp.GPIO_MODE.OUTPUT) # Reset the display esp.gpio_set_level(self.rst, 0) esp.task_delay_ms(100) esp.gpio_set_level(self.rst, 1) esp.task_delay_ms(100) # Send all the commands for cmd in self.init_cmds: self.send_cmd(cmd['cmd']) self.send_data(cmd['data']) if hasattr(cmd, 'delay'): task_delay_ms(cmd['delay']) print("ILI9341 initialization completed") # Enable backlight if self.backlight != -1: print("Enable backlight") esp.gpio_set_level(self.backlight, 1) ###################################################### flush_data = bytearray(4) def flush(self, disp_drv, area, color_p): # Column addresses self.send_cmd(0x2A) self.flush_data[0] = (area.x1 >> 8) & 0xFF self.flush_data[1] = area.x1 & 0xFF self.flush_data[2] = (area.x2 >> 8) & 0xFF self.flush_data[3] = area.x2 & 0xFF self.send_data(self.flush_data) # Page addresses self.send_cmd(0x2B) self.flush_data[0] = (area.y1 >> 8) & 0xFF self.flush_data[1] = area.y1 & 0xFF self.flush_data[2] = (area.y2 >> 8) & 0xFF self.flush_data[3] = area.y2 & 0xFF self.send_data(self.flush_data) # Memory write self.send_cmd(0x2C) size = (area.x2 - area.x1 + 1) * (area.y2 - area.y1 + 1) data_view = color_p.__dereference__(size * 2) self.send_data(data_view) lv.disp_flush_ready(disp_drv)