示例#1
0
    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()
示例#2
0
    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);
示例#3
0
    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")
示例#4
0
    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()
示例#5
0
 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)
示例#6
0
 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()
示例#7
0
    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
示例#10
0
 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)
示例#11
0
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
示例#12
0
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)
示例#13
0
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()
示例#14
0
    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)
示例#15
0
# 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()
示例#16
0
    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()
示例#17
0
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
示例#18
0
    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
示例#20
0
    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)