With the bit file generated, we are now able to create software that configures the ADV7611 Low-Power HDMI Receiver chip and the Zynq SoC’s VTC (Video Timing Controller). If we do this correctly, the VTC will then be able to report the input video mode.
To be able to receive and detect the video mode, the software must perform the following steps:
Initialize and configure the Zynq SoC’s I2C controller for master operation at 100KHz
Initialize and configure the VTC
Configure the ADV7611
Sample the VTC once a second, reporting the detected video mode
ZedBoard, FMC HDMI, and the PYNQ dev board connected for testing
Configuring the I2C and VTC is very simple. We have done both several times throughout this series (See these links: I2C, VTC.) Configuring the ADV7611 is more complicated and is performed using I2C. This is where this example gets a little complicated as the ADV7611 uses eight internal I2C slave addresses to configure different sub functions.
To reduce address-contention issues, seven of these addresses are user configurable. Only the IO Map has a fixed default address.
I2C addressing uses 7 bits. However, the ADV7611 documentation specifies 8-bit addresses, which includes a Read/Write bit. If we do not understand the translation between these 7- and 8-bit addresses, we will experience addressing issues because the Read/Write bit is set or cleared depending on the function we call from XIICPS.h.
The picture below shows the conversion from 8-bit to 7-bit format. The simplest method is to shift the 8-bit address one place to the right.
We need to create a header file containing the commands to configure each of the eight ADV7611’s sub functions.
This raises the question of where to obtain the information to configure the ADV7611 device. Rather helpfully, the Analog Devices engineer zone, provides several resources including a recommended registers settings guide and several pre-tested scripts that you can download and use to configure the device for most use cases. All we need to do is select the desired use case and incorporate the commands into our header file.
One thing we must be very careful with is that the first command issued to the AD7611 must be an I2C reset command. You may see a NACK on the I2C bus in response to this command as the reset asserts very quickly. We also need to wait an appropriate period after issuing the reset command before continuing to load commands. In this example, I decided to wait the same time as following a hard reset, which the data sheet specifies as 5msec.
Once 5msec has elapsed following the reset, we can continue loading configuration data, which includes the Extended Display Identification Data (EDID) table. The EDID identifies to the source the capabilities of the display. Without a valid EDID table, the HDMI source will not start transmitting data.
Having properly configured the ADV7611, we may want to read back registers to ensure that it is properly configured or to access the device’s status. To do this successfully, we need to perform what is known as a I2C repeat start in the transaction following the initial I2C write. A repeat start is used when a master issues a write command and then wants to read back the result immediately. Issuing the repeat start prevents another device from interrupting the sequence.
We can configure the I2C controller to issue repeat starts between write and read operations within our software application by using the function call XIicPs_SetOptions(&Iic,XIICPS_REP_START_OPTION). Once we have completed the transaction we need to clear the repeat start option using the XIicPs_ClearOptions(&Iic,XIICPS_REP_START_OPTION) function call. Otherwise we may have issues with communication.
Once configured, the ADV7611 starts free running. It will generate HDMI Frames even with no source connected. The VTC will receive these input frames, lock to them and determine the video mode. We can obtain both the timing parameters and video mode by using the VTC API. The video modes that can be detected are:
Initially in its free-running mode, the ADV7611 outputs video in 480x640 pixel format. Checking the VTC registers, it is also possible to observe that the detector has locked with the incoming sync signals and has detected the mode correctly, as shown in the image below:
With the free-running mode functioning properly, the next step is to stimulate the FMC HDMI with different resolutions to ensure that they are correctly detected.
To test the application, we will use a PYNQ Dev Board. The PYNQ is ideal for this application because it is easily configured for different HDMI video standards using just a few lines of Python, as shown below. The only downside is the PYNQ board does not generate fully compliant 1080P video timing.
SVGA video outputting 800 pixels by 600 lines @ 60Hz
720P video outputting 1280 pixels by 720 Lines @ 60 Hz
SXGA video outputting 1280 pixels by 1024 lines @ 60Hz
Having performed these tests, it is clear the ADV7611 on the FMC HDMI is working as required and is receiving and decoding different HDMI resolutions correctly. At the same time, the VTC is correctly detecting the video mode, enabling us to capture video data on our Zynq SoC or Zynq UltraScale+ MPSoC systems for further processing.
The FMC HDMI has another method of receiving HDMI that equalizes the channel and passes it through to the Zynq SoC’s or Zynq UltraScale+ MPSoC’s PL for decoding. I will create an example design based upon that input over the next few weeks.
Note that we can also use this same approach with a MicroBlaze soft processor core instantiated in a Xilinx FPGA.