Closed reaper7 closed 8 years ago
Well, have to admit, is not clear to me what is going on in ESp8266 SPI! Foe example, the SPI.trasfer16 is 'awesome slow' on ESP8266. Last week I get stuck for a couple of days with SPI.writePattern that in many cases should increase a lot speed, works for chunks of 8bit but when repeating 16 bit chunks, not clear if this happen at what SPI speed. Another discover of this week is the 'weak' SCLK signal coming from the 5 ESP8266 NodeMCU.0.9 and 1.0 modules I have here, all between 1.6 and 2.2v, so weak that my 74HC125 buffer I use to isolate RA8875 don't work and this open possibilities to add compatibility to my RA8875 library Another question is:SPI.write are protected by SPI transactions? But thanks for suggestions and keep suggesting, I will look at it and let you know.
Regard your question: SPI.writePattern is pretty fast, I used extensively on fills and pixel streams. SPI.trasfer is NOT fast or better, can be much faster. The reason I'm still using is maintain compatibility with SPI bus and other possible devices, remember that SPI.transfer are protected by SPI transactions
see result from Your benchark example, tested with ILI9163C (from https://github.com/sumotoy/TFT_ILI9163C/tree/Pre-Release-1.0p7) NodeMCU0.9, CPU 80MHz times with original code:
Benchmark Time (microseconds)
Screen fill 300231
Text 14493
Text2 42718
Lines 129856
Horiz/Vert Lines 28162
Rectangles (outline) 23002
Rectangles (filled) 457897
Circles (filled) 87643
Circles (outline) 86561
Triangles (outline) 41060
Triangles (filled) 175108
Rounded rects (outline) 50240
Rounded rects (filled) 521248
Done!
and with SPI.write inside spiwrite original replaced by SPI.write(c); inside spiwrite16 original replaced by SPI.write16(c);
Benchmark Time (microseconds)
Screen fill 237725
Text 12176
Text2 37076
Lines 115615
Horiz/Vert Lines 22987
Rectangles (outline) 18801
Rectangles (filled) 362660
Circles (filled) 72630
Circles (outline) 73988
Triangles (outline) 34936
Triangles (filled) 143534
Rounded rects (outline) 42597
Rounded rects (filled) 415042
code for test:
void spiwrite(uint8_t c)
__attribute__((always_inline)) {
#if 0
SPI.transfer(c);
#else
SPI.write(c);
#endif
}
void spiwrite16(uint16_t c)
__attribute__((always_inline)) {
#if 0
#if defined(_SPI_MULTITRANSFER)
//last version of ESP8266 for arduino support this
uint8_t pattern[2] = { (uint8_t)(c >> 8), (uint8_t)(c >> 0) };
SPI.writePattern(pattern, 2, (uint8_t)1);
#else
SPI.transfer(c >> 8); SPI.transfer(c >> 0);
#endif
//SPI.transfer(c >> 8); SPI.transfer(c >> 0);
#else
SPI.write16(c);
#endif
}
when I look inside SPI.cpp, difference between transfer and write is only one,
transfer at the end of function return value:
return (uint8_t) (SPI1W0 & 0xff);
and the same changes for TFT_ST7735 1.0p1 wemos d1 mini ; 160MHz
without changes:
Benchmark Time (microseconds)
Screen fill 233058
Text 9056
Text2 25514
Lines 94073
Horiz/Vert Lines 21288
Rectangles (outline) 14110
Rectangles (filled) 284433
Circles (filled) 71166
Circles (outline) 67614
Triangles (outline) 23119
Triangles (filled) 107096
Rounded rects (outline) 30484
Rounded rects (filled) 320356
Done!
and with changes (transfer -> write:
Benchmark Time (microseconds)
Screen fill 201062
Text 8061
Text2 23068
Lines 86223
Horiz/Vert Lines 18613
Rectangles (outline) 12344
Rectangles (filled) 245378
Circles (filled) 62796
Circles (outline) 60561
Triangles (outline) 21095
Triangles (filled) 93883
Rounded rects (outline) 27200
Rounded rects (filled) 277700
Done!
and additional raport...my display do not work when inside: TFT_ST7735_cpuCommons.h spi speed is set to: static const uint32_t TFT_ST7735_SPI_SPEED = 80000000; but works when speed value is 79999999 and below very strange!
Thanks point me this! I will up a modded version with your suggestions in a min for both libraries, in settings there's the flag to enable the trick (with your name as thanks of course). Or you prefere pull a request? Let me know. Regards the SPI speed, this is a know issue and I never understand why (if you look at closed issues in ILI library you will find). What is really strange that works at very high speed on Teensy 3.2 but not on ESP! The only thing I've noticed is that at 80Mhz (but in reality is NOT) the level of the SCLK drops even more (it's enough very weak, should be 3v3 but I've measured 1.6..2.2V) and waveform became distorted, maybe too much for the ST7735. I will try to add an high speed Schmitt trigger later and see what happen. Did you know if the internal flash uses the same SPI line?
Did you know if the internal flash uses the same SPI line?
You wrote about esp? in my knowledge no, "internal" esp flash uses second spi line.
Or you prefere pull a request? Let me know.
Plaese, do it. I don't want to deform so nicely developed library structure
I think something like this:
inside TFT_ST7735_cpuCommons.h -> at the end ESP section ?
but with a small change... for me and for compatibility inside spiwrite16 it should only apply to _SPI_MULTITRANSFER:
void spiwrite16(uint16_t c)
__attribute__((always_inline)) {
#if defined(_SPI_MULTITRANSFER)
#if !defined(_SPI_WRITEMOD)
//last version of ESP8266 for arduino support this
uint8_t pattern[2] = { (uint8_t)(c >> 8), (uint8_t)(c >> 0) };
SPI.writePattern(pattern, 2, (uint8_t)1);
#else
SPI.write16(c);
#endif
#else
SPI.transfer(c >> 8); SPI.transfer(c >> 0);
#endif
}
Ok, put this inside settings file:
/*--------------------------------------------------------------------------------
- ESP8266 Faster SPI -
This force library to use the SPI.write method instead the legacy SPI.transfer.
As result is much faster. (Thanks Reaper7)
Default:uncommented
----------------------------------------------------------------------------------*/
#if defined(ESP8266)
#define _ESP8266_SPIFAST
#endif
then inside .h file
void spiwrite(uint8_t c)
__attribute__((always_inline)) {
#if defined(_ESP8266_SPIFAST)
SPI.write(c);
#else
SPI.transfer(c);
#endif
}
void spiwrite16(uint16_t c)
__attribute__((always_inline)) {
#if defined(_ESP8266_SPIFAST)
SPI.write16(c);
#else
#if defined(_SPI_MULTITRANSFER)
//last version of ESP8266 for arduino support this
uint8_t pattern[2] = { (uint8_t)(c >> 8), (uint8_t)(c >> 0) };
SPI.writePattern(pattern, 2, (uint8_t)1);
#else
SPI.transfer(c >> 8); SPI.transfer(c >> 0);
#endif
#endif
}
ok, tnx!
Sorry, are you gonna pull a request or I update as proposed above?
please, do it yourself as You suggested above
I have a question about https://github.com/sumotoy/TFT_ST7735/blob/1.0p1/TFT_ST7735.h#L536 and https://github.com/sumotoy/TFT_ST7735/blob/1.0p1/TFT_ST7735.h#L542 SPI.transfer is faster way for "only write" data to spi bus than SPI.write ?
and one more question: https://github.com/sumotoy/TFT_ST7735/blob/1.0p1/TFT_ST7735.h#L547 SPI.writePattern vs SPI.write16 maybe simple write16 will be faster?