Edzelf/ESP32-Radio

Noise updating SPI OLED

fixus971 opened this issue · 16 comments

Hi.

I created an include file to use the display
OLED 3V - 2.42" 128x64 SPI SSD1309
I connected via SPI

To make the display control file I started from the most similar file: ILI9341.h
because I used the library: Adafruit_SSD1306

I'm trying to figure out how I can pass the display driver file and changes to you.
I also updated the main file and now everything works.

Unfortunately I hear noise with every update of the display that I have optimized to minimize it: 1 update () every second instead of the initial 20.

I have detected the times and the update of the SPI display lasts 2ms but this is not the cause because by replacing with a delay (100) those disturbances do not appear.

The disturbance feels like when bits of data are missing.
I am studying the code but it is not easy to understand all the round from the server to the internal cache that sends the data to the decoder.

I am looking for a way to understand which buffer is emptying or freezing.

Could there be a problem in SPI sharing between display and ESP?

Are there any debug writings that can be activated?

Thanks

Your display has an SPI interface. So it needs something like the "blueftf" driver.
Note that the VS1053 also uses SPI. Therefore a semaphore must be used to separate the 2 data streams. The semaphore is called "SPIsem".
See the "claimSPI" function. So before refreshing the screen, you must claim the SPI bus and after completion you need to use "releaseSPI" to free the bus.
You driver needs to have a "dsp_usesSPI" function (or macro) that always returns "true". Than the "spftask" (which handles the display) will know that it has to claim the SPI bus.
Note that using "delay" will not delay the "playtask". In fact it will give more CPU time to the playtask. In the ESP32 (FreeRTOS), a delay is not a wait-loop, but it will just postpone the execution of the calling task.

Hi, thanks for the quick reply.

Unfortunately in the example shown: "blueftf" there is no "claimSPI" function.

And I didn't enter it because I saw that it is already called in main.cpp based on
dsp_usesSPI which I set to "true":

`void handle_spec()
{
// Do some special function if necessary

if ( dsp_usesSPI() ) // Does display uses SPI?
{
claimSPI ( "hspectft" ) ; // Yes, claim SPI bus
}
if ( tft ) // Need to update TFT?
{
handle_tft_txt() ; //<< // Yes, TFT refresh necessary
}
if ( dsp_usesSPI() ) // Does display uses SPI?
{
releaseSPI() ; // Yes, release SPI bus
}`

I found example in CH376.h:
claimSPI ( "usbopen3" ) ; .. releaseSPI() ;

inserting claimSPI ("mywork"); ... releaseSPI ();
the situation is getting worse!:

D: Semaphore is claimed by hspectft
D: SPI semaphore not taken within 20740 ticks by CPU 0, id dsp_update_display
D: Semaphore is claimed by hithin 2
D: SPI semaphore not taken within 20570 ticks by CPU 0, id stopsong
D: Semaphore is claimed by hspectft
D: SPI semaphore not taken within 20750 ticks by CPU 0, id dsp_update_display
D: Semaphore is claimed bn within 2
D: SPI semaphore not taken within 20580 ticks by CPU 0, id stopsong
D: Semaphore is claimed by hspectf2D: SPI semaphore not taken within 20760 ticks by CPU 0, id dsp_update_display

Now I understand that by setting:
dsp_usesSPI () = true
SPI (and audio update) is blocked unnecessarily during the graphic update which in my case takes place in the CPU and not sending commands to the display.

So I set:
dsp_usesSPI () = false
and made use of
claimSPI("dsp_update"); tft->display(); releaseSPI();
only around the update function which sends data via SPI.
Now works!!

but listening to relaxation radio with continuous sounds ..
..I still hear a few small clicks every second.

Maybe.. could there be an SPI speed change interfering somewhere?

Thanks

You should set dsp_usesSPI () = true.
This will cause the SPI resource to switch between display and decoder without interference.
But you have to make sure thate the update of the screen is fast.
Therefore the screen is divided into sections (see tftdata). Only refresh a section if the section has been changed ( tftdata[i].update_req == true ).

I know of the zone update but I have not found it in the lib made by Adafruit.
I have found that this update time is 2ms and I think and hope that the buffer time in the VS1053 player is much longer.
Or am I wrong?

I have another app that works with this screen and does FFT audio with real time graph with no problem .. here without SPI sharing.

2 ms would be great. But I do not trust this figure. It would mean 500 frames per second.... Very unlikely.
I think the 2 ms is the time to store the data in the SPI output buffer. After that the SPI bus is occupied for a much longer period. You can estimat this time by multiplying the number of bits in the display divided by the bitrate of the SPI bus.

Yes: 2ms is only time to send data via SPI.
But I limited the updates to 1 frame / sec.

then free the SPI bus because I have verified that the other GFX functions do not use the SPI bus because they work in internal memory.

I also tried adding delay without detecting audio variations.
But the noises only disappear when I skip the screen update line via SPI

My conclusion is that without segmenting the screen update it will be impossible to service the VS1053 in time.

Hi Ed; I discovered the mystery.
The problem was hardware on DC(Data/Command) signal sharing with OLED:
I thought it was XDCS; instead this is a second CS to differentiate the VS1053's input and output chip selection.
Now I can hear well and update the full screen almost in real time (every 5ms, not less).

Unfortunately, however, I found that the audio buffer of the VS1053 is reduced to only 140ms of audio:
if I send only audio data for 1000ms
then I can't pause more than 140ms.

I thought it held a little more audio buffer internally

Can you confirm me more or less?

Thanks.

I do not understand. First you say that all is well, and then you say there is a lack of fifo space in the VS1053?

HI. I resolve conflict with oled DC pin. no more noise on display update.
update of 3ms.
Testing and stressing.. removing display..
I found a limit of 140ms on vs1053 audio buffer

So it is just an observation, no issue. Good!

Yes, thanks for your time

hello
I am trying to use SSD1309 in SPI mode too. Can you please explain me more in detail the modifications you made to make it work ?
Now I have 3 SPI hardwares :

  • vs1053
  • SSD1309 OLED display
  • CH376 USB driver

can you please help ?

Short wires (5 cm or less). Not mixed with other wires.
Good GND connections.
Lower the main SPI Clock frequency.

yes but I would need a little bit more detail...
like maybe the "SSD1309.h" driver.
I tried to write one, based on the BLUETFT.h (using the ADAFRUIT SSD1309 library, but it does not seem to work.
Testing each hardware indivualy and they work almost fine.
could you help ?