2023-08-17 04:51 AM - edited 2023-08-17 04:54 AM
There are many questions around related to the DCMI and embedded syncs on various forums. ST's documentation is not very helpful in this regard and I could not find any meaningful solutions on the web.
The reference manual is a bit terse on what needs to be done but gives a hint or two.
DCMI_ESUR=0xFFFFFFFF; DCMI_ESCR=0xB69D80AB;
If you are happy with capturing just one field - set ESCR either to odd or even field codes as you desire. If you need both fields then set DCMI_ESUR=0xB0B0B0B0 so it ignores the field bit.
Enable DCMI interrupts for HSync and VSync - you can ignore the rest. In your interrupt count the 0x18 and 0x10 states of MIR before you clear the flags. The sum of both gives you the number of lines of active video plus Vsync period for the total lines for the captured field. If you are allowing both odd and even the count will tell you if you just captured an odd or even field. During the VSync, at time of your choosing setup a DMA to start a new capture (1440 bytes per line if PAL or NTSC). The DCMI will give you the active pixels only (not the ones in the HSync period). Ensure you use the DMA with FIFO enabled in word (32 bit) mode. It's only 4 words deep but you need it - the pixels come in fast. In my case I setup a DMA in double buffer circular mode writing just two lines into internal SRAM which is fast. At every end of transfer (one line) I use the MDMA to copy the last line received from SRAM to DRAM into the final frame buffer - here you can use the MDMA larger internal FIFO nicely. You need to avoid overruns on the DCMI and also pay attention to race conditions between DCMI interrupts and DMA interrupts. I'm doing this in the M4 to avoid the interrupt latency in Linux. If you capture just odd or even fields - increment your frame buffer line address by your stride - if it's odd and even increment by twice the stride taking care of setting the correct start line address after a VSYNC depending on your count of lines which gives you odd or even field. Cropping does not work in embedded sync mode - but can easily be achieved using your MDMA and a line counter. Finally - users of the STM32MP157 may have noticed that ST forgot to include some means of hardware conversion from YCbYCr to RGB (the DMA2D does not exist here). In later chip revisions the LDTC can do it but not very useful since likely you need to scale before display and you really don't want to do that in software with YCbYCr. I am using Linux and Mesa3D - use at least version 23.1.4 - earlier has bugs related to ETNAVIV driver. Use OpenGL and have your MDMA write to a GBM BO you use as external texture - then use a shader to do the conversion from YCbYCr to RGB. Hint: ARGB format fits nicely for one YCbYCr word. Bonus - since the image is a texture you can map it to anything - from just a rectangular image to wrapping it around a shape. That's nice. Also the texture filtering works and can improve the image slightly at, surprisingly, almost zero cost.
My framebuffer in DRAM holds three complete images cycling so to avoid any chance of tearing as OpenGL drawing to renderbuffer is not synchronized with camera frame capture. Depending on your system you may have to do this whole mess outside of Linux as existing drivers may not work at all - they may react on the error and overrun as well as frame flags which should just be ignored here. I used the M4 cpu to do the heavy lifting here and OpenGL just finds a camera image magically appearing in a texture. The DCMI will work with any line length or line count - with embedded syncs you get the active line data (so your DMA must be setup for that) - not the syncs and not the data between start and end of HSync. You do get the active line data during the vertical sync period.
I am using the DCMI with a TVP5151 (almost identical to TVP5150) and PAL as well as NTSC cameras. The line count I keep track of tells me if I have PAL or NTSC so the texture parameters for OpenGL rendering can be automatically adjusted.