lvgl / lv_binding_micropython

LVGL binding for MicroPython
MIT License
237 stars 156 forks source link

RP2 Port: 'module' object has no attribute 'disp_drv_t' #303

Closed robin7331 closed 7 months ago

robin7331 commented 7 months ago

Hey there! I'm trying to get my RP2 Pico working with LVGL but I had no luck so far. Maybe I'm missing something obvious?

I am building lv_micropython using this GitHub Action:

on:
  push:
    branches:
      - main

jobs:
  local-build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Project
        uses: actions/checkout@v4
      - name: Checkout LVGL
        uses: actions/checkout@v4
        with:
          repository: lvgl/lv_micropython
          ref: "b1301ee8359454fd8b68b4063874e5034b4d9fe5" # Last commit on master
          path: "./lv_micropython"
          submodules: true
      - name: Update apt-get
        run: sudo apt-get update
      - name: Install packages
        run: sudo apt-get install gcc-arm-none-eabi libnewlib-arm-none-eabi build-essential cmake git python3 -y
      - name: Init Submodules
        run: |
          cd "$GITHUB_WORKSPACE/lv_micropython"
          git submodule update --init --recursive lib/lv_bindings
      - name: Make RP2 / PICO Submodules
        run: |
          cd "$GITHUB_WORKSPACE/lv_micropython"
          make -j$(nproc) -C ports/rp2 BOARD=PICO USER_C_MODULES=../../lib/lv_bindings/bindings.cmake submodules
      - name: Make mpy-cross
        run: |
          cd "$GITHUB_WORKSPACE/lv_micropython"
          make -j$(nproc) -C mpy-cross
      - name: Make Firmware
        run: |
          cd "$GITHUB_WORKSPACE/lv_micropython"
          make -j$(nproc) -C ports/rp2 BOARD=PICO USER_C_MODULES=../../lib/lv_bindings/bindings.cmake
          mv $GITHUB_WORKSPACE/lv_micropython/ports/rp2/build-PICO/firmware.uf2 $GITHUB_WORKSPACE/firmware.uf2

The build works. Once I flash the UF2 to my Pico I can for example successfully import and init lvgl via

import lvgl as lv
lv.init()

but once I try to register a display driver I get the AttributeError: 'module' object has no attribute 'disp_drv_t' error.

# Register the display driver
disp_drv = lv.disp_drv_t()      # This line fails
disp_drv.init()
disp_drv.flush_cb = lvgl_flush_cb
disp_drv.hor_res = DISPLAY_WIDTH
disp_drv.ver_res = DISPLAY_HEIGHT
disp_drv.register()

Does anybody know what the issue is here? Thanks in advance!

robin7331 commented 7 months ago

Here's the full contents of the main.py file:

import lvgl as lv
import machine
import rp2_dma
import time

# Constants for the display
SPI_FREQUENCY = const(40000000)  # 40 MHz
SPI_MOSI = 7  # Change to your MOSI pin
SPI_SCK = 6   # Change to your SCK pin
SPI_CS = 9    # Change to your CS pin
DISPLAY_WIDTH = const(240)
DISPLAY_HEIGHT = const(320)

# Initialize LVGL
lv.init()

# Configure the SPI bus
spi = machine.SPI(
    0, 
    baudrate=SPI_FREQUENCY,
    sck=machine.Pin(SPI_SCK, machine.Pin.OUT),
    mosi=machine.Pin(SPI_MOSI, machine.Pin.OUT),
)

# Configure the CS pin for the display
cs = machine.Pin(SPI_CS, machine.Pin.OUT)
cs(1)  # Deselect the display

# Initialize DMA
dma = rp2_dma.DMA(0)  # Use DMA channel 0

# Configure the SPI for the ILI9341 initialization
spi.init(baudrate=SPI_FREQUENCY)

# Write ILI9341 initialization sequence using spi.write()
# ... (omitted for brevity, see ILI9341 datasheet or existing drivers for commands)

# Helper function to transfer data using DMA
def dma_transfer(spi, cs, data):
    cs(0)  # Select the display
    # Configure the DMA to transfer data to SPI TX, then start the transfer
    dma.config(
        src_addr=uctypes.addressof(data),
        dst_addr=spi._spi[1],  # SPI1 TX FIFO
        count=len(data),
        src_inc=True,
        dst_inc=False,
        trig_dreq=rp2_dma.DMA.DREQ_SPI1_TX
    )
    dma.enable()
    # Wait for the transfer to complete
    while dma.is_busy():
        pass
    cs(1)  # Deselect the display

# LVGL Display Driver Flush Callback
def lvgl_flush_cb(drv, area, color_p):
    # Convert the LVGL color buffer to a byte array compatible with DMA transfer
    color_size = lv.color_t.SIZE * area.get_size()
    buf = bytearray(color_size)
    color_p_buf = uctypes.bytearray_at(color_p.__dereference__(color_size), color_size)
    buf[:] = color_p_buf
    # Use the helper function to transfer the buffer to the display
    dma_transfer(spi, cs, buf)
    # Indicate to LVGL that flushing is done
    drv.flush_ready()

# Register the display driver
disp_drv = lv.disp_drv_t()
disp_drv.init()
disp_drv.flush_cb = lvgl_flush_cb
disp_drv.hor_res = DISPLAY_WIDTH
disp_drv.ver_res = DISPLAY_HEIGHT
disp_drv.register()

# Create a screen and a simple label
scr = lv.obj()
label = lv.label(scr)
label.set_text("Hello, ILI9341!")
label.align(lv.ALIGN.CENTER, 0, 0)
lv.scr_load(scr)

# Your main loop
while True:
    lv.task_handler()
    time.sleep_ms(5)
robin7331 commented 7 months ago

Thought the forum might be the better place to post this question so I created a new thread: https://forum.lvgl.io/t/rp2-pico-module-object-has-no-attribute-disp-drv-t/13557

Feel free to delete the issue or leave it here for people with the same issue. Sorry for the duplicate!

robin7331 commented 7 months ago

Solved the issue by using the release/v8 branch of lv_micropython instead of master. For some reason the HAL files were missing on master. See here