tinygo-org / tinygo

Go compiler for small places. Microcontrollers, WebAssembly (WASM/WASI), and command-line tools. Based on LLVM.
https://tinygo.org
Other
14.75k stars 862 forks source link

TinyGo ST7789 Display Driver not working with Pimoroni Explorer Base (RPI Pico based development board) #3383

Open AndreClot opened 1 year ago

AndreClot commented 1 year ago

I believe that there may be some issues with the TinyGo ST7789 display driver that manifests itself on the Pimoroni Explorer Base https://shop.pimoroni.com/products/pico-explorer-base?variant=32369514315859

I have tried to configure the TinyGo ST7789 display driver for pico on the Pimoroni Explorer to no avail. I contacted Pimoroni and although they tried to be very helpful it didn"t work for me. This led me to believe that there may be a problem with the TinyGo driver. I can get their MicroPython to drive the display with no problem but not with the TinyGo drivers.

The attached is the TinyyGo code I use to configure the display. It manages to light up the screen giving a static kaleidoscope of coloured lines. No display commands that I tried do anything to change this situation. It is as if the display is locked. Changing Mode to 1 does however give a blank black screen but nothing else works after that.

The Pimoroni Explorer display uses 4 pico pins: GP16, GP 17, GP 18, GP 19. It is a 240 x 240 display.

machine.SPI0.Configure(machine.SPIConfig{ Frequency: 80000, DataBits: 8, // valid values 4..16 default 8 SCK: machine.GP18, // SCK / SPI0_SCK_PIN SDO: machine.GP19, // TX MOSI / SPI0_SDO_PIN SDI: machine.GP16, // RX MISO / SPI0_SDI_PIN Mode: 0, // CPOL=1, CPHA=0 })

// Pins GP1, GP2, and GP3 are defined as it appears the driver requires them although they do not appear to do anything.

display := st7789.New(machine.SPI0, machine.GP1, // dcPin Not connected machine.GP2, // resetPin Not connected machine.GP17, // csPin machine.GP3) // blPin Not connected

display.Configure(st7789.Config{ Width: 240, // 240 Height: 240, // 240 Rotation: st7789.NO_ROTATION, // Rotation Value = 0 RowOffset: 0, // int16 ColumnOffset: 0, // int16 FrameRate: st7789.FRAMERATE_60, // framerate Value = 60 VSyncLines: st7789.MAX_VSYNC_SCANLINES, // int16 */ })

Since the TinyGo ST7789 have been tested on the Adafruit Clue I am sure that this is a minor error but I have tried numerous combinations in the above but have failed miserably over the last months.

I can only hope that whoever wrote the drivers can perhaps point the way to a solution as I really want to start using TinyGo on the Explorer Base.

If you conclude that the drivers is fine then at least I have discounted one area.

Many thanks for any help.

soypat commented 1 year ago

I'm very curious as to whether this is a bug on the RP2040's side. I've bought a couple ST7789's to test this out.

AndreClot commented 1 year ago

Hi Patricio

Many thanks for looking at this. If it helps I have tried the Pico Explorer Base board again with Micropython and it still works OK. The board uses your own supplied RP2040 that you slot in. I did buy a spi ST7789 display for the breakout slot but that did not work so I am guessing your test might highlight what is happening.

Your help is much appreciated

Best regards

Andre

PS It was your video that got me looking at Go and it is a breath of fresh air after using Python and C/C++ on the Pico 👍

On Sat, 14 Jan 2023, 14:36 Patricio Whittingslow, @.***> wrote:

I'm very curious as to whether this is a bug on the RP2040's side. I've bought a couple ST7789's to test this out.

— Reply to this email directly, view it on GitHub https://github.com/tinygo-org/tinygo/issues/3383#issuecomment-1382755585, or unsubscribe https://github.com/notifications/unsubscribe-auth/ATQWF3VSGIPCK45ZDUMXY5DWSK2XLANCNFSM6AAAAAAT2WCK5Y . You are receiving this because you authored the thread.Message ID: @.***>

soypat commented 1 year ago

Sorry I did not get to this. Implementing the wifi driver for the Pico W is driving me mad. I could suggest you try to use a bitbang SPI to see if the issue is with the pico's hardware SPI or the driver. Here's the implementation: https://github.com/soypat/cyw43439/blob/main/bbspi.go. I've tested it thoroughly and it seems to get the job done.

AndreClot commented 1 year ago

Thanks, I'll check it out.

On Sun, 26 Feb 2023, 23:09 Patricio Whittingslow, @.***> wrote:

Sorry I did not get to this. Implementing the wifi driver for the Pico W is driving me mad. I could suggest you try to use a bitbang SPI to see if the issue is with the pico's hardware SPI or the driver. Here's the implementation: https://github.com/soypat/cyw43439/blob/main/bbspi.go

— Reply to this email directly, view it on GitHub https://github.com/tinygo-org/tinygo/issues/3383#issuecomment-1445494378, or unsubscribe https://github.com/notifications/unsubscribe-auth/ATQWF3SV2YG3YJVARPO5NY3WZPPDBANCNFSM6AAAAAAT2WCK5Y . You are receiving this because you authored the thread.Message ID: @.***>

soypat commented 1 year ago

I have been able to replicate this issue on a raspberry pi pico with hardware SPI.

Will try to get around to seeing if the software SPI has different results.

AndreClot commented 1 year ago

Thank you for having a look at this again. I did try a few more things but to no avail. I got an email from someone also trying to get a solution so perhaps there are more people that will benefit from your efforts.. I will direct them to this issue trail. 😀

aykevl commented 1 year ago

Have you tried SPI mode 3? I believe that's the mode that's usually needed for the ST7789.

soypat commented 1 year ago

Following program works on the Waveshare zero, both with SPI Mode 0 and SPI Mode 3 (I had made a mistake during initialization before)

https://github.com/tinygo-org/tinygo/assets/26156425/3d02a1ac-6cfa-4292-9a9b-3e6a0bf50b38

package main

import (
    "image/color"
    "machine"
    "time"

    "tinygo.org/x/drivers/st7789"
)

var (
    testSPIBuf []byte
    display    st7789.Device
    white      = color.RGBA{255, 255, 255, 255}
    red        = color.RGBA{255, 0, 0, 255}
    blue       = color.RGBA{0, 0, 255, 255}
    green      = color.RGBA{0, 255, 0, 255}
    black      = color.RGBA{0, 0, 0, 255}
)

func main() {
    setup()
    for {
        println("fill red")
        display.FillScreen(red)
        time.Sleep(time.Second)
        println("fill green")
        display.FillScreen(green)
        time.Sleep(time.Second)
        println("fill blue")
        display.FillScreen(blue)

        time.Sleep(time.Second)
    }
}

func setup() {
    const (
        width, height = 240, 135
        cs            = machine.GPIO4
        dc            = machine.GPIO28
        res           = machine.GPIO29
        blk           = machine.GPIO27
    )
    cs.Configure(machine.PinConfig{Mode: machine.PinOutput})
    dc.Configure(machine.PinConfig{Mode: machine.PinOutput})
    res.Configure(machine.PinConfig{Mode: machine.PinOutput})
    blk.Configure(machine.PinConfig{Mode: machine.PinOutput})

    var err error
    bus := machine.SPI0
    err = bus.Configure(machine.SPIConfig{
        Frequency: 800000,
        SCK:       machine.GPIO2,
        SDO:       machine.GPIO3,
        SDI:       machine.GPIO0,
        Mode:      0b11,
    })
    if err != nil {
        panic(err.Error())
    }

    display = st7789.New(bus, res, dc, cs, blk)
    display.Configure(st7789.Config{
        Rotation:   st7789.NO_ROTATION,
        RowOffset:  0,
        FrameRate:  st7789.FRAMERATE_111,
        VSyncLines: st7789.MAX_VSYNC_SCANLINES,
        Width:      height,
        Height:     width,
    })
}
AndreClot commented 1 year ago

I tried the code below modified to fit the pin layout of the Pimoroni Explorer Board (see attached) but it still failed to respond even though Micropython worked fine.

The board did gently glow as it started up but that was it. I am really foxed.

However the upside is that I am getting much better at using Go now.

Many thanks again, and at least we have a driver that works better in other configurations.

On 5 Jun 2023, at 21:33, Andre Clot @.***> wrote:

On 3 Jun 2023, at 17:24, Patricio Whittingslow @.***> wrote:

Following program works on the Waveshare zero, both with SPI Mode 0 and SPI Mode 3 (I had made a mistake during initialization before)

https://github.com/tinygo-org/tinygo/assets/26156425/3d02a1ac-6cfa-4292-9a9b-3e6a0bf50b38

package main

import ( "image/color" "machine" "time"

"tinygo.org/x/drivers/st7789" )

var ( testSPIBuf []byte display st7789.Device white = color.RGBA{255, 255, 255, 255} red = color.RGBA{255, 0, 0, 255} blue = color.RGBA{0, 0, 255, 255} green = color.RGBA{0, 255, 0, 255} black = color.RGBA{0, 0, 0, 255} )

func main() { setup() for { println("fill red") display.FillScreen(red) time.Sleep(time.Second) println("fill green") display.FillScreen(green) time.Sleep(time.Second) println("fill blue") display.FillScreen(blue)

 time.Sleep(time.Second)

} }

func setup() { const ( width, height = 240, 135 cs = machine.GPIO4 dc = machine.GPIO28 res = machine.GPIO29 blk = machine.GPIO27 ) cs.Configure(machine.PinConfig{Mode: machine.PinOutput}) dc.Configure(machine.PinConfig{Mode: machine.PinOutput}) res.Configure(machine.PinConfig{Mode: machine.PinOutput}) blk.Configure(machine.PinConfig{Mode: machine.PinOutput})

var err error bus := machine.SPI0 err = bus.Configure(machine.SPIConfig{ Frequency: 800000, SCK: machine.GPIO2, SDO: machine.GPIO3, SDI: machine.GPIO0, Mode: 0b11, }) if err != nil { panic(err.Error()) }

display = st7789.New(bus, res, dc, cs, blk) display.Configure(st7789.Config{ Rotation: st7789.NO_ROTATION, RowOffset: 0, FrameRate: st7789.FRAMERATE_111, VSyncLines: st7789.MAX_VSYNC_SCANLINES, Width: height, Height: width, }) } — Reply to this email directly, view it on GitHub https://github.com/tinygo-org/tinygo/issues/3383#issuecomment-1575051131, or unsubscribe https://github.com/notifications/unsubscribe-auth/ATQWF3RSHAAZ3DP2XS4SNHDXJNQMNANCNFSM6AAAAAAT2WCK5Y. You are receiving this because you authored the thread.

soypat commented 1 year ago

Andre, out of curiosity: what version of tinygo are you running? You can check with tinygo version in console.

AndreClot commented 1 year ago

Patricio

The version comes up as:

tinygo version 0.27.0 darwin/amd64 (using go version go1.20.4 and LLVM version 15.0.0)

I use this on a Mac Mini M1

On 11 Jun 2023, at 19:30, Patricio Whittingslow @.***> wrote:

Andre, out of curiosity: what version of tinygo are you running? You can check with tinygo version in console.

— Reply to this email directly, view it on GitHub https://github.com/tinygo-org/tinygo/issues/3383#issuecomment-1586275445, or unsubscribe https://github.com/notifications/unsubscribe-auth/ATQWF3TXAV2B36YZZGBKHLLXKYFDHANCNFSM6AAAAAAT2WCK5Y. You are receiving this because you authored the thread.

deadprogram commented 1 month ago

Checking in here @AndreClot @soypat is this still a problem in recent versions, or can we now close?

AndreClot commented 1 month ago

I never did get it working and moved on to other things. I did have one other who flagged the same issue but I am happy for this to be closed.

On Sun, 12 May 2024, 13:55 Ron Evans, @.***> wrote:

Checking in here @AndreClot https://github.com/AndreClot @soypat https://github.com/soypat is this still a problem in recent versions, or can we now close?

— Reply to this email directly, view it on GitHub https://github.com/tinygo-org/tinygo/issues/3383#issuecomment-2106238097, or unsubscribe https://github.com/notifications/unsubscribe-auth/ATQWF3RJEHA2FEBCKWAYOQLZB5RDHAVCNFSM6AAAAAAT2WCK52VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCMBWGIZTQMBZG4 . You are receiving this because you were mentioned.Message ID: @.***>

hendersonh commented 1 month ago

This code will send text or graphics to the onbord ST7789 disply on the Pinorami Pico Express. st7789.txt The next comment is the code: This works on the Pinmorani Pico Express. After determing how the board had wired the display to the PICO's GPIO pins, it was a simple task of using tinygo to send graphics and text to the display using tinyfont and tinydraw. I hope someone find the code useful.

AndreClot commented 1 month ago

Many thanks for trying this. It confirms to me that something in the configuration of the pimoroni pico explorer is somehow different to what is advertised on the back of it. MicroPython works fine on the display but for me at least the go code example, which compiled just fine, should work but doesn't. I will leave this issue open for a month or so in case we have a lightbulb moment. I did look at the pio code in the Micropython source but it was beyond me to understand what was going on. Many thanks again for trying.

hendersonh commented 1 month ago

The code works on the Pinorami Pico Explorer board. I had to look at the their C++ drivers to determin how they had connected the display to the PICO's GPIO.

hendersonh commented 1 month ago
// Tinygo code to send text to ST7789 display. The display is connected to a Rasberry Pi PICO.
// Send text or draw on the ST7789 display using the SPI protocol.
// keywords: send text to lcd display using SPI protocol configure ST7789 connected to PICO
package main
import (
//  "image/color"
//"crypto/aes"
"image/color"
"log"
"machine"
"time"
"tinygo.org/x/drivers/st7789"
//"tinygo.org/x/tinydraw"
"tinygo.org/x/tinyfont"
"tinygo.org/x/tinyfont/freemono"
)
var (
dc = machine.GPIO16
cs = machine.GPIO17
unused = machine.NoPin
)
func main() {
spiPort := machine.SPI0
err := spiPort.Configure(machine.SPIConfig {
SCK: machine.GPIO18,
SDO: machine.GPIO19,
SDI: machine.GPIO16,
Mode: machine.Mode3,
})
if err != nil {
log.Fatalf("failed to configure SPI: %v", err)
}
display := st7789.New(spiPort, unused, dc, cs, unused)
display.Configure(st7789.Config{
Width: 240,
Height: 240,
})
display.FillScreen(color.RGBA{0,0,0,255})
display.Display()
white := color.RGBA{255, 255, 255, 255}
  // Draw text "hendy" at position (10, 10)
  tinyfont.WriteLine(&display, &tinyfont.TomThumb, 10, 10, "Hello", color.RGBA{255, 255, 255, 255})
 //  display.FillRectangle(240/2, 0, 240/2, 240/2, white)// Refresh the display
//  display.Display()
display.FillScreen(color.RGBA{0,0,0,255})
tinyfont.WriteLineRotated(&display,
&freemono.Bold9pt7b, 11, 14, "Hendy Hood is a good man, always.", white, tinyfont.NO_ROTATION )
time.Sleep(10 * time.Second)
}