-
Notifications
You must be signed in to change notification settings - Fork 201
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
spi: remove machine.SPI and replace with drivers.SPI interface #208
Conversation
…most all SPI drivers Signed-off-by: deadprogram <[email protected]>
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.
I'm all in favor of this change, but there is an unresolved issue: how to configure the SPI peripheral from a driver?
The most difficult case is the flash driver. The flash chip is only known during configuration, not before (unless the user tells the driver which flash chip it is, which is less flexible). Therefore, either the flash driver would have to assume a (lower) safe default speed or have a SetFrequency
.
I'm leaning towards adding a SetFrequency
(which is really a "set max frequency" as the actual frequency may be lower than requested due to hardware limitations). This would of course need to be supported in the machine package for every supported chip. But still not sure about it.
What do you think? @deadprogram @conejoninja
I think adding a Note that we are going to have to deal with similar issue when we need to implement What should we do about the |
Signed-off-by: deadprogram <[email protected]>
I think it should use plain SPI communication as defined in |
@aykevl @deadprogram If machine.SPI.Tx() is fast, we can use machine.SPI.Tx(). I'm considering the following code. I am also considering using DMA. func (spi *machine.SPI) Tx(tx, rx []byte) {
spi.Bus.DATA.Set(uint32(tx[0]))
for !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_DRE) {
}
for i := 1; i < len(rx); i++ {
spi.Bus.DATA.Set(uint32(tx[i]))
for !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_RXC) {
}
rx[i-1] = byte(spi.Bus.DATA.Get())
//time.Sleep(10 * time.Microsecond)
}
for !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_RXC) {
}
rx[len(rx)-1] = byte(spi.Bus.DATA.Get())
} If you rewrite ili9341/spi_atsamd51.go as follows, it will run at similar speed. var txBuf = [(136 + 8) * (100 + 8) * 2]uint8{}
func (pd *spiDriver) write16sl(data []uint16) {
// This part of the data can be eliminated by reversing the endian of the data
// and using []bytes as input data.
// Or we can create something like Tx(d []uint16) that takes []uint16 as an argument.
for i, c := 0, len(data); i < c; i++ {
txBuf[i*2+0] = uint8(data[i] >> 8)
txBuf[i*2+1] = uint8(data[i])
}
pd.bus.Tx3(txBuf[:len(data)*2])
} |
Ideally what I would like to be able to do is remove entirely the samd21 and samd51 special code used by that driver. If we can make it so it only needs to use the |
You can use a standard machine.SPI driver with the following combination.
However, the 44 fps is slowed down to 24 fps.
There are two ways to increase the speed
|
@aykevl @deadprogram https://github.com/tinygo-org/drivers/commits/spi-bus-samd5x-drivers
|
I changed the pattern for using the See https://github.com/tinygo-org/drivers/blob/spi-bus/wifinina/wifinina.go#L272-L281 and https://github.com/tinygo-org/drivers/blob/spi-bus/examples/wifinina/mqttclient/main.go#L63-L68 |
You are probably initializing some global here, you can move the initialization to the |
Which method are you using? One workaround could be to send buffers in batches, for example by allocating 32 bytes, preparing it and sending that. That should avoid most of the inefficiency. In general I think the API for these displays can be improved for speed, but I'm not yet sure how exactly. The original |
i am eager to merge this PR, but still seems like we need to resolve a couple of items.
@sago35 @aykevl @bgould or anyone else please chime in. Thanks. |
I would suggest doing the flash driver changes in a later commit, after TinyGo has gained something like a Right now the default SPI speed is 4MHz (see tinygo-org/tinygo#1447). I checked the supported SPI chips and all of them support at least 8MHz (with many supporting crazy high clock frequencies such as 65MHz) so there isn't a need to use a lower frequency at startup. So an alternative to delaying the
For regular (blocking) SPI transactions the current API should suffice and fast implementations are possible (see tinygo-org/tinygo#1517 for example). Aside from my issue with the flash driver, this change looks good to me. |
Yes, I am using DrawRGBBitmap. It is more efficient to create a Buffer of a certain size first.
ILI9341-pyportal-boing is a slow process, but I will try to improve ILI9341-driver later. |
…il we implement SetClockSpeed() Signed-off-by: deadprogram <[email protected]>
…direct gpio Signed-off-by: deadprogram <[email protected]>
OK I have now put the flash driver back how it was before. I have also added a Everything is green, so I think this can now be merged. |
Going to merge now, thanks everyone for the feedback! |
This PR removes
machine.SPI
and replaces them with thedrivers.SPI
interface for almost all SPI drivers.There are a couple of drivers that will require additional or special handling. Primarily this has to do with #206
The
flash
driver will require changes to any consumers to set the SPI speed before calling into the driver.The
ili9342
driver has very tight coupling to specific SPI code that probably belongs in themachine
package:https://github.com/tinygo-org/drivers/blob/release/ili9341/spi_atsamd21.go
https://github.com/tinygo-org/drivers/blob/release/ili9341/spi_atsamd51.go