-
Notifications
You must be signed in to change notification settings - Fork 196
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ILI9341 TFT driver (SPI) #153
Conversation
|
Using 32bit-extension made it a little faster.
|
The reason CI is failing is that there is no function for 32bit extensions that I added below. |
ili9341/spi_atsamd51.go
Outdated
func (pd *spiDriver) configure(config *Config) { | ||
} | ||
|
||
//go:inline |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do all these //go:inline
annotations really improve performance?
In general they should only be added as a fix for performance. Also, before doing that please test with -opt=2
first because that will likely make the //go:inline
pragmas unnecessary (and you should add -opt=2
if speed is important).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
go:inline is something I copied from parallel_atsamd51.go.
I wasn't particularly aware of it.
Removing go:inline didn't change the speed.
So, I'll remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The FPS didn't change when I set -opt=2.
By using INTEFLAG.DRE, I was able to improve performance without using 32bit-extensions. There is one area that bothers me. The pyportal parallel_atsamd51.go is similarly slow, but converges from 51 fps to 49 fps.
|
I don't understand why CircleCI failed.
|
|
Looks like the build problem is this:
|
Now I know why the CI test was failing. But this time, I got a different error.
|
@deadprogram diff: 2ac3d61 ci before: https://circleci.com/gh/tinygo-org/drivers/468 |
rebased. |
I think the CI issue was that we were checking out in |
rebased. |
I have tested on PyPortal and it is noticeably faster. Good work @sago35 thank you! @aykevl @bgould @conejoninja any last feedback before I squash/merge this? |
wioterminal.go did not need power control, so I removed it. |
Removed unnecessary pins in struct. |
I'm working on another driver for spi with DMA, but I'll be creating a separate PR for it.
The source code is below, but refactoring is required. |
Any feedback on this @conejoninja or @bgould ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated. (5cd2e05)
Since the actual values were the same, the behavior remains the same.
SERCOM_SPIS_CTRLB_RXEN = 0x20000 // Bit RXEN.
SERCOM_SPIS_INTFLAG_DRE = 0x1 // Bit DRE.
SERCOM_SPIS_SYNCBUSY_CTRLB = 0x4 // Bit CTRLB.
SERCOM_SPIM_CTRLB_RXEN = 0x20000 // Bit RXEN.
SERCOM_SPIM_INTFLAG_DRE = 0x1 // Bit DRE.
SERCOM_SPIM_SYNCBUSY_CTRLB = 0x4 // Bit CTRLB.
ili9341/spi_atsamd51.go
Outdated
} | ||
|
||
func (pd *spiDriver) write8(b byte) { | ||
pd.bus.Bus.CTRLB.ClearBits(sam.SERCOM_SPIS_CTRLB_RXEN) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's SPIM, not SPIS, so it needs to be fixed
@deadprogram How are you testing this on pyportal? Did you have to cut and short the traces on the back to switch it into SPI mode, or some other way? The ILI9341 board I have is my pyportal so just curious if I need to do that (I want to try out the DMA improvement when its ready so I don't mind making that change if it is necessary) |
No I did not modify my PyPortal. I do have a WioTerminal now that I am using for testing. |
@sago35 are you going to add your DMA code to this PR? |
Did not test it, but the code looks good to me. Maybe the driver interface should be in a separate file, or at the beginning of ili6341.go (I like to put on top var declarations, structs, and interfaces, not sure if that follows the go guidelines) |
For DMA support, a wait is required after DMA transfer and before SPI transmission (or CS/DC, etc.). The following is a great library, and it would be easier to make a good library if you focus on SPI + DMA only, as shown below. |
Using DMA in the following way will not change the speed. func (pd *spiDriver) write16sl(data []uint16) {
pd.DmaSend16(data)
for !sam.DMAC.CHANNEL[pd.dmaChannel].CHINTFLAG.HasBits(sam.DMAC_CHANNEL_CHINTFLAG_TCMPL) {
}
sam.DMAC.CHANNEL[pd.dmaChannel].CHINTFLAG.SetBits(sam.DMAC_CHANNEL_CHINTFLAG_TCMPL)
} |
Not really pertinent to this PR, but pretty sure DMA is possible with the parallel interface also - https://www.youtube.com/watch?v=ClabKcWVxT8 - there is C code demonstrating that in the Adafruit ILI9341 driver for Arduino, it is a little hard to read though IMO especially because it is buried inside #ifdefs. I'm not going modify my pyportal at this time to test, the code looks good to me though. Probably DMA could be handled separately; I imagine that possibly could require a new driver interface - I believe @aykevl might have some ideas about that and also the current work to make blocking operations in TinyGo work properly with interrupts could come into play as well. Thats all to say that the SPI driver looks good to me and DMA support could be integrated separately IMO. Nice work @sago35 :) |
I am going to squash/merge this PR now. Thank you very much @sago35 for another awesome contribution! |
@bgould My latest try was 136 fps, but adafruit's video is a bit faster than that. pyportal_boing 136 fps with TinyGo + Wio Terminal |
Since DMA is not supposed to be able to do DMA on ports, I guess it's like inverting wr with TC while rewriting RAM with DMA. |
I also tried the SPI by shorting out the jumper on the PyPortal board, but the screen did not appear. It is important to note that TFT_RS and SCK are shorted by the jumper. The feather-m4 and the external SPI ILI9341 worked correctly, so I think something is wrong with the settings. |
My intention is the following:
|
I tried again, and the SPI driver works on the PyPortal. It is best not to use ILI9341, such as blinky, before working with it. |
examples/ili9341/pyportal_boing/pyportal.go // +build pyportal
package main
import (
"machine"
"tinygo.org/x/drivers/ili9341"
)
var (
display = ili9341.NewSpi(
machine.SPI0,
machine.TFT_WR, // In SPI mode, WR is used instead of DC.
machine.TFT_CS,
//machine.NoPin,
machine.TFT_RESET,
)
backlight = machine.TFT_BACKLIGHT
)
func init() {
machine.SPI0.Configure(machine.SPIConfig{
SCK: machine.SPI0_SCK_PIN,
MOSI: machine.SPI0_MOSI_PIN,
MISO: machine.SPI0_MISO_PIN,
LSBFirst: false,
Mode: machine.Mode0,
Frequency: 40000000,
})
machine.D34.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.D34.Low()
machine.D35.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.D35.Low()
machine.D36.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.D36.Low()
machine.D37.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.D37.Low()
machine.D38.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.D38.Low()
machine.D39.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.D39.Low()
machine.D40.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.D40.Low()
machine.D41.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.D41.Low()
machine.TFT_RD.Configure(machine.PinConfig{Mode: machine.PinOutput})
machine.TFT_RD.High()
machine.TFT_DC.Configure(machine.PinConfig{Mode: machine.PinInput})
} |
* ili9341: Add spidriver
This PR adds SPI support for the ILI9341.