Video
1080p...
So far I achieved half-resolution of 1080p. The video signal is 1080p widescreen, HOWEVER, every pixel is doubled - every pixel in the memory is rendered as 2x2 pixels on the screen. True 1080p is theoretically achievable. The RAM is somewhat limited on the STM32L4s but it's still possible to fit.
The OCTOSPI is capable of outputting the necessary 148 Mb/s data rate at a 74MHz system clock in the double data rate mode. The DMA also should be able to deliver at the necessary data rate of 1 transfer every 16 clock cycles.
So... coming soon! ☠👈🏻
Schematic
An absolute minimalist design. Because all the 3 color lines on the VGA connector are connected together, the impedance matching cannot be done well - hence, some shadowing will appear in the image.
This HW version is only a preliminary solution that I use to verify the viability of this project. A good solution has to have 3 independent drivers - all impedance matched individually to the 75Ω color lines. This can be achieved for example with a cheap logic gate IC from the 7400 family.
However, because there are only 2 colors, slight shadows don't really degrade the image quality.
Functional Block Diagram
Nearly all of the necessary functions are executed automatically by the integrated peripherals. The only software intervention needed is setting up the DMA CH2 for every line.
DMA CH1 is triggered by a hardware timer directly. It writes a single word to the OCTOSPI. This ensures a stable start timing for the OCTOSPI, thus, a stable pixel alignment.
At the same time the DMA CH2 is set up and started, so it will immediately begin to transmit the pixel data to the OCTOSPI. The OCTOSPI data transfer is already running, so, as long as the buffer doesn't run out, the pixel timing and alignment remains correct.
I did something similar with a PIC32MZ at one point (I had three different tries at it, one using SPI for monochrome, one using a lower resolution 8bpp (R2G2B2X2) framebuffer, and a third with an even lower resolution 16bpp (R5G6B5) framebuffer).
I learned an interesting and hard lesson: If there are any JTAG ports that overlap with your pixel outputs, be sure to disable them lest all hell break loose when you output the "right" sequence.
For the color framebuffer in the higher resolution mode I just set the clock source for both the DMA engine and the GPIO ports to the right multiple (2x IIRC) of the desired pixel clock and set the DMA master to have high priority. The GPIO ports weren't expected to operate over 50MHz but for an output destined just to be mashed into a R-2R DAC it seemed to work OK.
As usual available frame buffer memory is the real limiting factor.