Edzelf / ESP32-Radio

Internet radio based on ESP32, VS1053 and a TFT screen.
GNU General Public License v3.0
979 stars 229 forks source link

Noise updating SPI OLED #480

Open fixus971 opened 2 years ago

fixus971 commented 2 years ago

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

Edzelf commented 2 years ago

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.

fixus971 commented 2 years ago

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
fixus971 commented 2 years ago

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

Edzelf commented 2 years ago

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 ).

fixus971 commented 2 years ago

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.

Edzelf commented 2 years ago

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.

fixus971 commented 2 years ago

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

Edzelf commented 2 years ago

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

fixus971 commented 2 years ago

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.

Edzelf commented 2 years ago

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?

fixus971 commented 2 years ago

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

Edzelf commented 2 years ago

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

fixus971 commented 2 years ago

Yes, thanks for your time

goguelnikov commented 1 year ago

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 :

can you please help ?

aly-fly commented 1 year ago

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

goguelnikov commented 1 year ago

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 ?