Page 1 of 2

VGA output: Can SPI make and send infinite circular buffer?

Posted: Thu Dec 21, 2017 4:18 pm
by ta-mat
VGA output: Can SPI make and send infinite circular buffer?

Hi, I'm new to ESP32 and esp-idf. But I have a question about SPI interface in ESP32.

My question is: Is ESP32's master mode SPI able to use (infinite) circular buffer which is defined DMA linked list descriptor?

My project is output VGA signal via SPI (800x600 video pixels, Pixel frequency is 40MHz, single frame contains 1056x628 pixel cycles as a signal). I choose SPI because ESP32 has QSPI which may enable RGB or RGBI output without clock skew. Also since ESP32's SPI can't generate 25.175MHz pixel frequency (640x480 "standard" VGA) signal, I choose 40MHz as pixel frequency which can be generated by ESP32's SPI.

As a first step, I tried to generate V-Sync and H-Sync pulse by LED_PWM. So far, it seems okay. My display properly recognize these siganls as 800x600@60Hz VGA input.

As a next step, I want to generate color signals by SPI.

Firstly, I've tried H-Sync interrupt by connecting GPIO output pin from LEDC to dedicated input pin for GPIO interrupt. But unfortunately, there's higher priority interrupts. So my H-Sync interrupt routine is randomly jammed by these interrupts. Especially FreeRTOS's tick counter frequently disrupts H-Sync routine. Personally, I want to use ESP32 and esp-idf's superb functionality such as WiFi, Bluetooth, etc as is. So for now, I'd like to avoid to disable FreeRTOS's tick. Thus I gave up H-Sync interrupt.

Secondly, I've tried to make circular buffer for SPI's DMA. I supposed that I can use DMA linked list descriptor (lldesc_t) for it. I set first descriptor's address to last descriptor's next descriptor address. And it works fine for some seconds. But since there's SPI_USR_MOSI_DBITLEN descrease for each cycle, it eventually stop to send MOSI signal.

So back to my question. Is there any way to make infinite circular buffer by master mode SPI with DMA linked list descriptor?
Perhaps, my question is irrelevant for VGA output. If so, any advice is welcome.

Re: VGA output: Can SPI make and send infinite circular buffer?

Posted: Fri Dec 22, 2017 1:31 am
by ESP_Sprite
Hey, VGA, that has been on my ToDo-list for a long time but I never got around to actually trying it. I have no idea if SPI can do that kind of thing... will ask the digital team; perhaps they know a bit that can set the SPI subsystem to do infinite-length transfers. If any, if that is not the case, you can try I2S instead; it's 8-bit at minimum instead of the 4-bit for SPI, but it most certainly can do circular buffers.

Re: VGA output: Can SPI make and send infinite circular buffer?

Posted: Fri Dec 22, 2017 3:11 am
by ESP_Sprite
And I have a response from the engineer:
yes, in SPI DMA mode, SPI will alway transmit and receive data when you set the SPI_DMA_CONTINUE(BIT16) of SPI_DMA_CONF_REG.
I'd be very interested in any progress you make on this front, by the way; would love it if you'd keep us updated somehow.

Re: VGA output: Can SPI make and send infinite circular buffer?

Posted: Fri Dec 22, 2017 5:56 pm
by ta-mat
Thanks for the info, ESP_Sprite and the engineer from digital team. SPI_DMA_CONF_REG.SPI_DMA_CONTINUE (spi_dev_t::dma_conf.dma_continue) works like a charm!

Since it's late-night in my timezone, I'll write wrap-up about this experiment with source code tomorrow.

Anyway, here's a photo which doesn't prove anything but celebrate my experiment :)
esp32-vga-800x600-output-experiment.jpg
esp32-vga-800x600-output-experiment.jpg (1.4 MiB) Viewed 14025 times

Re: VGA output: Can SPI make and send infinite circular buffer?

Posted: Sat Dec 23, 2017 9:29 am
by ta-mat
Hi, I attached source code of my VGA experiment. Setup procedure is

(1) Check GpioPins in main/vga_experiment.cpp. You should define and connect 3 GPIO pins for VGA: V-Sync, H-Sync, Video (single pin).
(2) Run make menuconfig for setup.
(3) Run make -j flash monitor for build & run.

Hope someone find fun and better approach.


So far, this code has some major problems.

(1) SPI DMA clock keep delaying for each few minutes.
V-Sync and H-Sync signal generation is rock-solid. It doesn't slip any nano seconds at least 4 hours.
But relative timing between H-Sync and SPI DMA have problem. In my experiment, DMA's timing is delayed (I mean H-Sync backporch becomes longer, frontporch becomes shorter) for each 1 to 3 minutes (I still don't measure it). And length of delay is always increased 200..220 ns at once (maybe 8 to 9 DMA cycles).

(2) More accurate, reliable initialize procedure is needed.
Final part of main/vga_exeriment.cpp : myvga_init() uses empty for() loop to make H-Sync backporch (margin between H-Sync pulse and video signal). It's absolutely fragile. But if esp-idf has API which can wait precisely, I'd like to use it.
Also I'm not sure portDISABLE_INTERRRUPTS() prevent all interrupts or not.

(3) Check it reasonably conform VGA.
My display show something. But perhaps another display doesn't sync the signal. I'm not confident that my code outputs good enough VGA signal or not.

Anyway, that's it for today. Thanks again for your advices!

Re: VGA output: Can SPI make and send infinite circular buffer?

Posted: Sat Dec 23, 2017 10:16 am
by loboris
Great "experiment".
Could you put it on GitHub?

Re: VGA output: Can SPI make and send infinite circular buffer?

Posted: Sat Dec 23, 2017 1:38 pm
by Helter
Can you explain how did you converted a image to "esp-happy-holydays.pbm.c.include" ?

Re: VGA output: Can SPI make and send infinite circular buffer?

Posted: Sun Dec 24, 2017 2:44 am
by ta-mat
@ESP_Sprite, I think I've fixed issue 1 (timing between SPI DMA and LEDC timer is unstable). But solution seems strange.
When I set 0 to entire bit of spi_dev_t::mosi_dlen.usr_mosi_dbitlen (SPI_MOSI_DLEN_REG.SPI_USR_MOSI_BITLEN), it works fine. At least 5 hours, no delay happened. But when I set actual number of bits of circular buffer (I mean number of bits in single "loop") to SPI_USR_MOSI_BITLEN, it keep delaying. If you know anything about this behaviour, please let me know.

@loboris, thanks. And yes, I'll put this code on GitHub.

@Helter, It's C array version of 800x600 pixel PBM. Replacing procedure is: (1) Create PBM (2) Convert it to C file by using xxd or something (3) Replace the file and tweak imageHeaderBytes.

Re: VGA output: Can SPI make and send infinite circular buffer?

Posted: Sun Dec 24, 2017 9:10 am
by ta-mat
Hi, I've put my code on GitHub.
https://github.com/t-mat/esp32-vga-experiment

Since there's absolutely copyright/trademark issue, I've removed the Espressif logo picture from the code. Demo code just shows random pixels instead of the logo.

Re: VGA output: Can SPI make and send infinite circular buffer?

Posted: Sat Jan 06, 2018 4:47 pm
by ta-mat
Hi, I've revamped my code at https://github.com/t-mat/esp32-vga-experiment . I've refactored almost all codes, but major changes are
(1) Remove LED_PWMs
(2) Use two RMT channels instead of LED_PWM.
(3) Add proper V-Sync, H-Sync interrupt. (H-Sync interrput is not exposured though)
(4) Change bitmap pixel order [LSB,MSB] -> [Left,Right]. Previous version's order was [LSB,MSB] -> [Right,Left]