Skip to content
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

Better document that SPI speed is set with setSPISpeed after initR and not begin() #107

Open
marcmerlin opened this issue Jan 28, 2020 · 20 comments

Comments

@marcmerlin
Copy link
Contributor

marcmerlin commented Jan 28, 2020

With other TFTs, you set speed withtft->begin(spispeed)

With ST77xx, begin() is protected in Adafruit_ST77xx.h, so you cannot call tft->begin(tft_spi_speed). The documentation in the .cpp file therefore seem unusable:

/**************************************************************************/
/*!
    @brief  Initialize ST77xx chip. Connects to the ST77XX over SPI and
            sends initialization procedure commands
    @param  freq  Desired SPI clock frequency
*/
/**************************************************************************/
void Adafruit_ST77xx::begin(uint32_t freq) {
  if (!freq) {
    freq = SPI_DEFAULT_FREQ;
  }
  _freq = freq;      

Then we have this which basically ensures you can't call begin with a different frequency.

void Adafruit_ST77xx::commonInit(const uint8_t *cmdList) {
  begin();

As a result, The only way to change the SPI speed is to do

    // tft->begin(tft_spi_speed) // does not work and you don't need to call begin anyway
    tft->initR(INITR_BLACKTAB);
    tft->setSPISpeed(tft_spi_speed); // this works.

I'm not sure what's the best way to make this findable. Maybe put a hint in "void Adafruit_ST77xx::begin(uint32_t freq) {" ?

@ladyada
Copy link
Member

ladyada commented Jan 28, 2020

you could add a commented out line in an example

marcmerlin added a commit to marcmerlin/Adafruit-ST7735-Library that referenced this issue Feb 29, 2020
As discussed adafruit#107
give users a clue how to change SPI speed
@marcmerlin
Copy link
Contributor Author

marcmerlin commented Feb 29, 2020

Sorry for the delay @ladyada , done in #114

That said, back to void Adafruit_ST77xx::begin(uint32_t freq)
is there any way for it to be called with a frequency, or is it always called through InitR, in which case the freq argument is a bit misleading and should arguably be removed?
(I'm not pushing for this, but I was very confused to see the argument only to realize later that it didn't really seem possible to actually pass it)

@ladyada
Copy link
Member

ladyada commented Feb 29, 2020

thanks for the PR!

@ladyada
Copy link
Member

ladyada commented Feb 29, 2020

i think we could remove the argument, it is left over from a refactor

@marcmerlin
Copy link
Contributor Author

@ladyada yep, looks like it. Are you ok removing it, or getting help from @makermelissa to remove it, or would you like me to send a PR?

@ladyada
Copy link
Member

ladyada commented Mar 1, 2020

please send a PR, and we'll both take a look :)

@zoonman
Copy link

zoonman commented Dec 23, 2020

Guys, the way we have implemented that whole init process makes display unusable. Mine goes blank white because SPI starts @ 8 MHz and even I do set the frequency later it doesn't help.
Normally developer should be able to set frequency before initialization.

tft.setSPIFreqency(1000000); // set 1 MHz
tft.initR(); // init @ 1 MHz.

@mrguen
Copy link

mrguen commented Jun 14, 2021

Hello,

I have a program that was working on STM32F103CBT6 (Arduino core STM32 support) with Adafruit GFX and ST775 libraries but not anymore with new versions. I am quite certain this is related to the SPI. Could you clarify how to set the SPI speed ?

I am currently using

SPI.setClockDivider(SPI_CLOCK_DIV2); tft.initR(INITR_144GREENTAB);

@marcmerlin
Copy link
Contributor Author

@mrguen
tft->setSPISpeed(tft_spi_speed);

@mrguen
Copy link

mrguen commented Jun 15, 2021

@marcmerlin thanks

@ejdp62
Copy link

ejdp62 commented Jul 30, 2022

Hello, my 1.8" TFT display runs fine on SW SPI with he AdafruitST7735 library on a UNO.
It needs to be initialized as a GREENTAB display. It is a tad slow, so I would like to start using HW SPI.
It runs on SW SPI with all SPI-related wires connected to the pins needed for HW SPI.
After many trials and reading of webpages, I have not succeeded in getting it to work on HW SPI at all.

So, I took my scope out, and connected it to the serial clock wire.
In SW SPI mode, there is a clock of about 200 kHz, while in HW SPI mode, there is a clock of 8 MHz.
So, I may be looking at a speed problem (in my setup, the distance from chip to TFT is about 12 cm).

As a first step, I would like to lower the HW SPI speed, and see if I can get it work.
Then, I would like to see if I can increase the speed by, for example,
inserting resistors in the clock and data lines to dampen reflections.

I have tried the suggestion mentioned in a post above:

// tft->begin(tft_spi_speed) // does not work and you don't need to call begin anyway
tft->initR(INITR_BLACKTAB);
tft->setSPISpeed(tft_spi_speed); // this works.

But this doesn't work: the initialization fails!
This is confirmed by one of the later posts in this thread:

Guys, the way we have implemented that whole init process makes display unusable.
Mine goes blank white because SPI starts @ 8 MHz and even I do set the frequency later it doesn't help.
Normally developer should be able to set frequency before initialization.

tft.setSPIFreqency(1000000); // set 1 MHz
tft.initR(); // init @ 1 MHz.

This is exactly my situation: the screen simply goes blank...
I would like to set the speed to a lower value before initialization.

So the question is: how can I reduce the HW SPI speed while using the ST7735 library??

@ejdp62
Copy link

ejdp62 commented Jul 30, 2022

Update: given the information in the original post about what happens inside the libraries, I decided to do a hack.
Playing around with the defined value of SPI_DEFAULT_FREQ was successful.
First value I tried was 1000000 (1 MHz), chosen to approximately result in the SW SPI speed,
and it worked right off the bat! After a bit of trying, my display stops working somewhere between 6 and 8 MHz.
So for the time being, I use 6 MHz, giving me a speed increase of about a factor of 8 over SW SPI.
I will try to fiddle around a bit with resistors to see if the speed can be further improved.

Despite this success however, the question as stated in my previous post remains !!
(At least, I would not like to do this hack every time Adafruit decides to publish a new version....)

@ejdp62
Copy link

ejdp62 commented Jul 31, 2022

Update 2: After considering how the "old" way of setting SPI speed is done using a clock divider of a power of 2,
I guess that my display stops working somewhere between 4 and 8 MHz,
and that for the UNO controller anything in between is essentially meaningless.

Perhaps things change when I would switch to another device, if that device can make other SPI clocks.
But in that case, also my setup will change in other ways, like the SPI bus length.
And so the maximum clock that I can use for my display might also change (compared to my current setup).

So, given that in some systems the SPI bus wiring creates the speed bottleneck (my system may or may not be an example),
then how do I set or choose the SPI frequency parameter? What does the parameter mean anyway?
Is it the maximum speed of the display? Or of the physical bus? Or a combination of the two?

I understand that the display library tries to make things simple for the Arduino user,
but in doing it this way, it controls a parameter that is not (fully) in its scope in the system.
Example: consider what happens if the SPI bus connects to a display plus some other device,
especially if that device forms the speed bottleneck?

So, given that the maximum SPI speed may be determined by more than just the display itself,
the question is why the display library should set the SPI speed in the first place.
At least, the system designer/constructor should have the option of setting it outside the display library.
To me, it would make more sense to leave the maximum speed setting to the SPI library.

@marcmerlin
Copy link
Contributor Author

First, I would recommend ditching the uno, it can do things, but it's so old and obsolete, while costing more than an ESP32 which is vastly superior in many ways.
That being said, I have had SPI displays that didn't work past 10Mhz or so, and it was often due to my wiring, length, cross talk and quality of wires. When I talked to the same display with the same chip on a circuit board with proper copper traces, I was able to use 40 to 80Mhz.
Also, I recommend this TFT library, it's faster and has more options:
https://www.arduino.cc/reference/en/libraries/gfx-library-for-arduino/

@ejdp62
Copy link

ejdp62 commented Aug 4, 2022 via email

@ejdp62
Copy link

ejdp62 commented Aug 5, 2022 via email

@ejdp62
Copy link

ejdp62 commented Aug 5, 2022 via email

@ejdp62
Copy link

ejdp62 commented Aug 6, 2022 via email

@ejdp62
Copy link

ejdp62 commented Aug 13, 2022 via email

@marcmerlin
Copy link
Contributor Author

thanks for trying. HWSPI can be tricky, it either works or doesn't.
The only advice I have for you is wiring. I had issues with mine not working because of too many wires that were too long, causing cross talk and failures.
The same code that didn't work with the same ESP32 and same screen, worked when I used a PCB where everything had nice copper traces instead of my flimsy wires.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants