element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Raspberry Pi
  • Products
  • More
Raspberry Pi
Raspberry Pi Forum RPI Pico & ST7789 Display
  • Blog
  • Forum
  • Documents
  • Quiz
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Raspberry Pi to participate - click to join for free!
Featured Articles
Announcing Pi
Technical Specifications
Raspberry Pi FAQs
Win a Pi
Raspberry Pi Wishlist
Actions
  • Share
  • More
  • Cancel
Forum Thread Details
  • Replies 15 replies
  • Subscribers 661 subscribers
  • Views 16456 views
  • Users 0 members are here
  • st7789
  • rpi pico
Related

RPI Pico & ST7789 Display

scottiebabe
scottiebabe over 3 years ago

I purchased an off brand ST7789 1.3" Display a few months ago and recently decided it was time to try it out.

 

I did not realize it at the time but there isn't a consistent pinout between display boards. As it turns out the board I purchased did not pin out the chip-select (CS) line.

 

The ST7789 display driver will function without a CS line, however you need to configure the SPI mode (idle state, edge polarity) to communicate with the display. In most cases, I suppose that would be easy enough to change the display driver.

 

Now I wanted to make use of this display with a PI Pico and Micropython. Pimoroni provide a Micropython release with a small number additional libraries on top of MicroPython : https://github.com/pimoroni/pimoroni-pico (unlike CircuitPython which is significantly different from MicroPython).

 

I was trying to get their example code for one of their displays: https://shop.pimoroni.com/products/1-3-spi-colour-lcd-240x240-breakout to function with my off brand display. Unfortunately, I could not find a way to change the SPI operating mode of the display driver unless I wanted to compile their distribution from source (which I didn't want to do), the SPI initialization was all buried in C code.

 

An intsructables author provided a wonderful guide to breaking out the chip-select line: https://www.instructables.com/Adding-CS-Pin-to-13-LCD/  Many thanks. In the process of modify my display I learned a few things the hard way:

  • Rotated R1 90' to bypass the NPN switch
  • Tossed R2 away and used this as the CS pad
  • Be carful with getting the display too hot. The adhesive that held the display in place virtually no longer exists now image
  • Be carful cleaning! Or don't clean at all. I ended up relocating the flux residue with isopropyl from the PCB to inside the display housing and its now a little merky image

image

 

After the display modifications the display came to life!

 

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

 

I have never used one of these displays before, but I have to say I am impressed. I was able to get 35 FPS out of a 240x240 display running over SPI.

 

I still don't know what the best way to add graphics to the PICO is. The image I showed in the video was created with ffmpeg outputting a raw video frame:

 

ffmpeg -vcodec png -i img.png -vcodec rawvideo -f rawvideo -pix_fmt rgb565 img.raw

 

Of this random image cropped down to 240x240:

image

Loading the image from flash was very slow.

 

Update: Image Loading Speed

The framebuffer for the ST7789 is stored big-endian so when I was loading the Image I had endian swap in python which was really slow. I can endian swap the raw image file format using dd:

dd conv=swab if=img.raw of=img2.raw

Now loading the image is now significantly faster:

t1 = time.ticks_us()
with open('img2.raw', 'rb') as f:
    for j in range(0,240,24):
        display_buffer[480*j:(480*(j+24))] = f.read(240*48)

display.update() # only update display once now, remove those tabs!
print((time.ticks_us() - t1)/1000)

 

Which now runs in 232 ms 85 ms and appears more as a transition animation versus terribly slow code.

 

Update: Overclocking in MicroPython

One can adjust the system clock frequency in MicroPython by issuing the following command:

machine.freq(190_000_000) # set system clock in Hz

 

When MicroPython alters the system clock frequency, it also reconfigures the peripheral clock source from clk_sys to the external crystal oscillator.

image

 

So, if you want to maintain a high-speed SPI clock frequency, you need to set the clock mux back to clk_sys yourself by:

mem32[0x40008000+0x48] = 0x800

 

With the Pico running at 190 MHz I achieved the following:

     Rainbow Spinner: 53 FPS

     FFT Demo: 16 FPS

     Image Load + Draw: 56 ms (49ms letting the garbage collector run before the load)

 

Of course, there are no guarantees this will always work for every Pico and or display.

  • Sign in to reply
  • Cancel
Parents
  • scottiebabe
    scottiebabe over 3 years ago

    Color Fading Demo with 35 FPS

    Micropython Release: MicroPython with Pimoroni Libs (1010KB) - https://github.com/pimoroni/pimoroni-pico/releases/download/v0.2.7/pimoroni-pico-v0.2.7-micropython-v1.16.uf2

     

    Was derived from 2 Pimoroni sample python applications:

    https://github.com/pimoroni/pimoroni-pico/blob/main/micropython/examples/breakout_colourlcd240x240/demo.py

    https://github.com/pimoroni/pimoroni-pico/blob/main/micropython/examples/pico_display/rainbow.py

     

    The only notable changes I had to make were:

    • Configure a GPIO for the reset input of my display (active-low). RST must be set high to run.
    • After display initialization I modified the SPI0 clock speed to Fsys/2

     

    from machine import Pin, SPI, mem32
    import time
    import random
    import math
    from breakout_colourlcd240x240 import BreakoutColourLCD240x240
    
    rst = Pin(13,Pin.OUT)
    rst.value(1)
    
    width = BreakoutColourLCD240x240.WIDTH
    height = BreakoutColourLCD240x240.HEIGHT
    
    display_buffer = bytearray(width * height * 2)  # 2-bytes per pixel (RGB565)
    display = BreakoutColourLCD240x240(display_buffer)
    
    mem32[0x4003c000] = 0x007 # Configure SPI0 CLKFREQ for Fsys/2
    
    # Load Image from flash memory
    # Size is know to be 240x240 
    t1 = time.ticks_us()
    with open('img2.raw', 'rb') as f:
        for j in range(0,240,24):
            display_buffer[480*j:(480*(j+24))] = f.read(240*48)
            display.update()
    print((time.ticks_us() - t1)/1000)
    
    time.sleep(3)
    
    # From CPython Lib/colorsys.py
    def hsv_to_rgb(h, s, v):
        if s == 0.0:
            return v, v, v
        i = int(h * 6.0)
        f = (h * 6.0) - i
        p = v * (1.0 - s)
        q = v * (1.0 - s * f)
        t = v * (1.0 - s * (1.0 - f))
        i = i % 6
        if i == 0:
            return v, t, p
        if i == 1:
            return q, v, p
        if i == 2:
            return p, v, t
        if i == 3:
            return p, q, v
        if i == 4:
            return t, p, v
        if i == 5:
            return v, p, q
    
    h = 0
    t1 = time.ticks_us()
    fps=float('nan')
    phi=0
    while True:
        # run 30 frames before taking a timestamp
        for i in range(30):
            h += 3.7
            r, g, b = [int(255 * c) for c in hsv_to_rgb(h / 360.0, 1.0, 1.0)]  # rainbow magic
            display.set_pen(r, g, b)  # Set pen to a converted HSV value
            display.clear()           # Fill the screen with the colour
            display.set_pen(0, 0, 0)  # Set pen to black
            display.text("Scottie", 10, 10, 240, 6)  # Add some text
            display.text("FPS: {:1.1f}".format(fps), 10, 50, 240, 6)  # Add some text
            display.set_pen(0, 0, 0)  # Set pen to black
            phi = phi + math.pi/32 % 2*math.pi
            xp = int(120 + 40*math.sin(phi))
            yp = int(150 + 40*math.cos(phi))
            display.circle(xp,yp,4)
            xp = int(120 + 40*math.sin(phi+math.pi))
            yp = int(150 + 40*math.cos(phi+math.pi))
            display.circle(xp,yp,4)
            tm = time.localtime()
            display.text("{:02d}:{:02d}:{:02d}".format(tm[3],tm[4],tm[5]), 10, 220, 240, 3)  # Add some text
            display.update()          # Update the display
            
        fps = 30/(time.ticks_us()-t1)*1e6
        t1 = time.ticks_us()

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
Reply
  • scottiebabe
    scottiebabe over 3 years ago

    Color Fading Demo with 35 FPS

    Micropython Release: MicroPython with Pimoroni Libs (1010KB) - https://github.com/pimoroni/pimoroni-pico/releases/download/v0.2.7/pimoroni-pico-v0.2.7-micropython-v1.16.uf2

     

    Was derived from 2 Pimoroni sample python applications:

    https://github.com/pimoroni/pimoroni-pico/blob/main/micropython/examples/breakout_colourlcd240x240/demo.py

    https://github.com/pimoroni/pimoroni-pico/blob/main/micropython/examples/pico_display/rainbow.py

     

    The only notable changes I had to make were:

    • Configure a GPIO for the reset input of my display (active-low). RST must be set high to run.
    • After display initialization I modified the SPI0 clock speed to Fsys/2

     

    from machine import Pin, SPI, mem32
    import time
    import random
    import math
    from breakout_colourlcd240x240 import BreakoutColourLCD240x240
    
    rst = Pin(13,Pin.OUT)
    rst.value(1)
    
    width = BreakoutColourLCD240x240.WIDTH
    height = BreakoutColourLCD240x240.HEIGHT
    
    display_buffer = bytearray(width * height * 2)  # 2-bytes per pixel (RGB565)
    display = BreakoutColourLCD240x240(display_buffer)
    
    mem32[0x4003c000] = 0x007 # Configure SPI0 CLKFREQ for Fsys/2
    
    # Load Image from flash memory
    # Size is know to be 240x240 
    t1 = time.ticks_us()
    with open('img2.raw', 'rb') as f:
        for j in range(0,240,24):
            display_buffer[480*j:(480*(j+24))] = f.read(240*48)
            display.update()
    print((time.ticks_us() - t1)/1000)
    
    time.sleep(3)
    
    # From CPython Lib/colorsys.py
    def hsv_to_rgb(h, s, v):
        if s == 0.0:
            return v, v, v
        i = int(h * 6.0)
        f = (h * 6.0) - i
        p = v * (1.0 - s)
        q = v * (1.0 - s * f)
        t = v * (1.0 - s * (1.0 - f))
        i = i % 6
        if i == 0:
            return v, t, p
        if i == 1:
            return q, v, p
        if i == 2:
            return p, v, t
        if i == 3:
            return p, q, v
        if i == 4:
            return t, p, v
        if i == 5:
            return v, p, q
    
    h = 0
    t1 = time.ticks_us()
    fps=float('nan')
    phi=0
    while True:
        # run 30 frames before taking a timestamp
        for i in range(30):
            h += 3.7
            r, g, b = [int(255 * c) for c in hsv_to_rgb(h / 360.0, 1.0, 1.0)]  # rainbow magic
            display.set_pen(r, g, b)  # Set pen to a converted HSV value
            display.clear()           # Fill the screen with the colour
            display.set_pen(0, 0, 0)  # Set pen to black
            display.text("Scottie", 10, 10, 240, 6)  # Add some text
            display.text("FPS: {:1.1f}".format(fps), 10, 50, 240, 6)  # Add some text
            display.set_pen(0, 0, 0)  # Set pen to black
            phi = phi + math.pi/32 % 2*math.pi
            xp = int(120 + 40*math.sin(phi))
            yp = int(150 + 40*math.cos(phi))
            display.circle(xp,yp,4)
            xp = int(120 + 40*math.sin(phi+math.pi))
            yp = int(150 + 40*math.cos(phi+math.pi))
            display.circle(xp,yp,4)
            tm = time.localtime()
            display.text("{:02d}:{:02d}:{:02d}".format(tm[3],tm[4],tm[5]), 10, 220, 240, 3)  # Add some text
            display.update()          # Update the display
            
        fps = 30/(time.ticks_us()-t1)*1e6
        t1 = time.ticks_us()

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
Children
No Data
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube