首页 > 其他分享 >双MIPI摄像头图像系统设计

双MIPI摄像头图像系统设计

时间:2023-03-01 10:47:35浏览次数:63  
标签:Status MIPI return u8 XST printf xil 图像 摄像头

5899537f95aad84711b484d9d9e73059.png

介绍

FPGA 的一大优势是我们可以实现并行图像处理数据流。虽然任务比较重,但是我们不需要昂贵的 FPGA,我们可以使用成本低廉范围中的一个,例如 Spartan 7 或 Artix 7。对于这个项目,将展示如何设计一个简单的图像处理应用程序,该应用程序平行处理两个摄像头。

本项目主要使用 Digilent PCAM 扩展板。PCAM 扩展板为最多四个 PCAMS 提供接口。所以只需要有FMC接口的开发板都可以完成本项目移植。

777fa7ada2d721b30bf2683f711f819c.png

Vivado

为了让系统快速启动和运行,我们将从赛灵思的一个示例项目开始设计。要打开参考项目,我们需要首先创建一个针对自己开发板上 FPGA 的项目。

2161e9010380271be9646134b081df92.png

打开项目后,创建一个新的BD。

f3b1363f586c1ae600a717178e0070d0.png

打开BD后,在BD中添加一个 MIPI CSI2 IP。

37039a8d4fe3f4386b1a8b84c7c5ff87.png

要打开参考设计,右键单击 CSI2 IP并选择打开 IP 示例设计。

d1efb1630f3addff87074941acb33a13.png

我们将使用这个参考项目。首先要做的是移除 DSI 输出路径。这将为我们的图像处理平台释放 FPGA 中的逻辑资源。

下一步是添加以下元素以创建第二条图像处理通道。

  • CSI2 IP Block

  • Register Slices & concatenation

  • Sensor Demosaic

  • VDMA

  • AXI Switch

完成的设计应如下所示:

05bfee573da2b5cd241ef6fd343b60f5.png

除了 CSI2 IP 中的设置外,第二个图像处理通道与第一个相同。

5e987b227dd64c753a346c957ba34429.png

原始 CSI2 IP 设置

8c03503043af17af789013e1d7dab927.png

添加的 CSI2 IP 中的设置

9e8c9eb15a55dcc9bacbdbc9b5ae0af0.png

VDMA 内存设置

3cf216e8f3c3eee9bdfd967ced75edd5.png

Sensor Demosaic设置

d0ffbfa8ed203f5736e0493e67701e34.png

AXI4 Stream Switch

a603aa8d35bec023291984fd26974bf2.png

时钟有不同的上行和下行时钟

0ced2e54be528130c05338cfe8b275fa.png df353af52fa961494b29be13018f82fc.png

完成BD设计接下来就是针对硬件进行管脚约束。

一旦完成,我们就可以生成和构建项目并导出 XSA 用于软件开发。

该设备的利用率如下:

5db5fb15d9bc4094fb017e807651c005.png

软件开发

导出 XSA 后,我们可以创建一个新的 Vitis 项目,其中包含 hello world 应用程序。

从 hello world 应用程序 BSP 设置中,我们可以导入 MIPI CSI2 示例项目。

bc0b37cde535ba9351a20761d09b36dc.png

我们需要对这个项目进行一些更改。

首先是通过 IIC 与传感器通信并设置传感器。板上的 CSI2 Sensor与FPGA 的 I2C 并没有直接连接。通过一个I2C BUFFER,与四个sensor连接,因为sensor的地址是一样的。

这可以在 fucntion_prototpye.c 中提供的传感器配置函数中进行更改。

所以我们在配置运行之前需要选择多路复用器。

  1.   extern int SensorPreConfig(int pcam5c_mode) {
  2.    
  3.    
  4.     u32 Index, MaxIndex, MaxIndex1, MaxIndex2;
  5.     int Status;
  6.     SensorIicAddr = SENSOR_ADDRESS;
  7.    
  8.     u8 SP701mux_addr = 0x75;
  9.       u8 SP701mux_ch = 0x40;
  10.    
  11.       u8 PCAM_FMC_addr = 0x70;
  12.       u8 PCAM_FMC_ch = 0x01;
  13.    
  14.    
  15.       Status = XIic_SetAddress(&IicAdapter, XII_ADDR_TO_SEND_TYPE, SP701mux_addr);
  16.       if (Status != XST_SUCCESS) {
  17.      return XST_FAILURE;
  18.       }
  19.    
  20.       WriteBuffer[0] = SP701mux_ch;
  21.       Status = AdapterWriteData(1);
  22.      if (Status != XST_SUCCESS) {
  23.        printf("sp701 mux failed\n\r");
  24.        return XST_FAILURE;
  25.      }
  26.    
  27.       Status = XIic_SetAddress(&IicAdapter, XII_ADDR_TO_SEND_TYPE, PCAM_FMC_addr);
  28.       if (Status != XST_SUCCESS) {
  29.      return XST_FAILURE;
  30.       }
  31.    
  32.       WriteBuffer[0] = PCAM_FMC_ch;
  33.       Status = AdapterWriteData(1);
  34.      if (Status != XST_SUCCESS) {
  35.        printf("pcam mux failed\n\r");
  36.        return XST_FAILURE;
  37.      }
  38.    
  39.    
  40.    
  41.     Status = XIic_SetAddress(&IicAdapter, XII_ADDR_TO_SEND_TYPE, SensorIicAddr);
  42.     if (Status != XST_SUCCESS) {
  43.    return XST_FAILURE;
  44.     }
  45.    
  46.    
  47.     WritetoReg(0x31, 0x03, 0x11);
  48.     WritetoReg(0x30, 0x08, 0x82);
  49.    
  50.     Sensor_Delay();
  51.    
  52.    
  53.     MaxIndex = length_sensor_pre;
  54.     for(Index = 0; Index < (MaxIndex - 0); Index++)
  55.     {
  56.       WriteBuffer[0] = sensor_pre[Index].Address >> 8;
  57.    WriteBuffer[1] = sensor_pre[Index].Address;
  58.    WriteBuffer[2] = sensor_pre[Index].Data;
  59.    
  60.       Sensor_Delay();
  61.    
  62.    Status = AdapterWriteData(3);
  63.    if (Status != XST_SUCCESS) {
  64.      return XST_FAILURE;
  65.    }
  66.     }
  67.    
  68.    
  69.     WritetoReg(0x30, 0x08, 0x42);
  70.    
  71.    
  72.     MaxIndex1 = length_pcam5c_mode1;
  73.    
  74.     for(Index = 0; Index < (MaxIndex1 - 0); Index++)
  75.     {
  76.       WriteBuffer[0] = pcam5c_mode1[Index].Address >> 8;
  77.    WriteBuffer[1] = pcam5c_mode1[Index].Address;
  78.    WriteBuffer[2] = pcam5c_mode1[Index].Data;
  79.    
  80.       Sensor_Delay();
  81.    
  82.    Status = AdapterWriteData(3);
  83.    if (Status != XST_SUCCESS) {
  84.      return XST_FAILURE;
  85.    }
  86.     }
  87.    
  88.    
  89.     WritetoReg(0x30, 0x08, 0x02);
  90.     Sensor_Delay();
  91.     WritetoReg(0x30, 0x08, 0x42);
  92.    
  93.    
  94.     MaxIndex2 = length_sensor_list;
  95.    
  96.     for(Index = 0; Index < (MaxIndex2 - 0); Index++)
  97.     {
  98.       WriteBuffer[0] = sensor_list[Index].Address >> 8;
  99.    WriteBuffer[1] = sensor_list[Index].Address;
  100.    WriteBuffer[2] = sensor_list[Index].Data;
  101.    
  102.       Sensor_Delay();
  103.    
  104.    Status = AdapterWriteData(3);
  105.      if (Status != XST_SUCCESS) {
  106.     return XST_FAILURE;
  107.      }
  108.     }
  109.    
  110.    
  111.     if(Status != XST_SUCCESS) {
  112.       xil_printf("Error: in Writing entry status = %x \r\n", Status);
  113.       return XST_FAILURE;
  114.     }
  115.    
  116.     return XST_SUCCESS;
  117.    
  118.   }

由于我们添加了第二个 Demosaic,我们还需要更新其配置。

  1.   int demosaic()
  2.   {
  3.     demosaic_Config = XV_demosaic_LookupConfig(DEMOSAIC_DEVICE_ID);
  4.     XV_demosaic_CfgInitialize(&InstancePtr, demosaic_Config,
  5.                                demosaic_Config->BaseAddress);
  6.     XV_demosaic_Set_HwReg_width(&InstancePtr, 1920);
  7.     XV_demosaic_Set_HwReg_height(&InstancePtr, 1080);
  8.     XV_demosaic_Set_HwReg_bayer_phase(&InstancePtr, 0x3);
  9.     XV_demosaic_EnableAutoRestart(&InstancePtr);
  10.     XV_demosaic_Start(&InstancePtr);
  11.    
  12.     demosaic_Config1 = XV_demosaic_LookupConfig(DEMOSAIC_DEVICE1_ID);
  13.     XV_demosaic_CfgInitialize(&InstancePtr1, demosaic_Config1,
  14.                                demosaic_Config1->BaseAddress);
  15.     XV_demosaic_Set_HwReg_width(&InstancePtr1, 1920);
  16.     XV_demosaic_Set_HwReg_height(&InstancePtr1, 1080);
  17.     XV_demosaic_Set_HwReg_bayer_phase(&InstancePtr1, 0x3);
  18.     XV_demosaic_EnableAutoRestart(&InstancePtr1);
  19.     XV_demosaic_Start(&InstancePtr1);
  20.     return XST_SUCCESS;
  21.    
  22.   }

最后阶段是设置第二个 DMA,这里必须注意 DDR3地址管理以确保帧不会相互重叠。

  1.   int vdma_hdmi() {
  2.    
  3.     InitVprocSs_CSC(1);
  4.    
  5.     ResetVDMA();
  6.    
  7.     RunVDMA(&AxiVdma, XPAR_AXI_VDMA_0_DEVICE_ID, HORIZONTAL_RESOLUTION, \
  8.       VERTICAL_RESOLUTION, srcBuffer, FRAME_COUNTER, 0);
  9.    
  10.     RunVDMA(&AxiVdma1, XPAR_AXI_VDMA_1_DEVICE_ID, HORIZONTAL_RESOLUTION, \
  11.       VERTICAL_RESOLUTION, srcBuffer1, FRAME_COUNTER, 0);
  12.    
  13.     return XST_SUCCESS;
  14.    
  15.   }

我们还需要注释掉 DSI 和TPG等函数使用的任何代码。

主代码也需要更新,以便在串口命令下控制 AXI Switch。

  1.   /******************************************************************************
  2.   * Copyright (C) 2018 - 2022 Xilinx, Inc.  All rights reserved.
  3.   * SPDX-License-Identifier: MIT
  4.   *******************************************************************************/
  5.    
  6.   /*****************************************************************************/
  7.   /**
  8.   *
  9.   * @file xmipi_sp701_example.c
  10.   *
  11.   * <pre>
  12.   * MODIFICATION HISTORY:
  13.   *
  14.   * Ver   Who    Date     Changes
  15.   * ----- ------ -------- --------------------------------------------------
  16.   * X.XX  XX     YY/MM/DD
  17.   * 1.00  RHe    19/09/20 Initial release.
  18.   * </pre>
  19.   *
  20.   ******************************************************************************/
  21.   /***************************** Include Files *********************************/
  22.    
  23.   #include "xparameters.h"
  24.   #include "xiic.h"
  25.   #include "xil_exception.h"
  26.   #include "function_prototype.h"
  27.   #include "pcam_5C_cfgs.h"
  28.   #include "xstatus.h"
  29.   #include "sleep.h"
  30.   #include "xiic_l.h"
  31.   #include "xil_io.h"
  32.   #include "xil_types.h"
  33.   //#include "xv_tpg.h"
  34.   #include "xil_cache.h"
  35.   #include "stdio.h"
  36.   #include "xaxis_switch.h"
  37.    
  38.    
  39.    
  40.   /************************** Constant Definitions *****************************/
  41.    
  42.    
  43.   #define PAGE_SIZE   16
  44.   #define XAXIS_SWITCH_DEVICE_ID  XPAR_AXIS_SWITCH_0_DEVICE_ID
  45.    
  46.   #define IIC_BASE_ADDRESS XPAR_IIC_2_BASEADDR
  47.    
  48.   #define EEPROM_TEST_START_ADDRESS 0x80
  49.    
  50.   #define IIC_SWITCH_ADDRESS 0x74
  51.   #define IIC_ADV7511_ADDRESS 0x39
  52.   //XV_tpg_Config  *tpg1_Config;XV_tpg_Config  *tpg1_Config;
  53.   //XV_tpg    tpg1;
  54.   //XV_tpg    tpg1;
  55.   typedef u8 AddressType;
  56.    
  57.   typedef struct {
  58.    u8 addr;
  59.    u8 data;
  60.    u8 init;
  61.   } HDMI_REG;
  62.    
  63.   #define NUMBER_OF_HDMI_REGS  16
  64.   HDMI_REG hdmi_iic[NUMBER_OF_HDMI_REGS] = {
  65.    {0x41, 0x00, 0x10},
  66.    {0x98, 0x00, 0x03},
  67.    {0x9A, 0x00, 0xE0},
  68.    {0x9C, 0x00, 0x30},
  69.    {0x9D, 0x00, 0x61},
  70.    {0xA2, 0x00, 0xA4},
  71.    {0xA3, 0x00, 0xA4},
  72.    {0xE0, 0x00, 0xD0},
  73.    {0xF9, 0x00, 0x00},
  74.    {0x18, 0x00, 0xE7},
  75.       {0x55, 0x00, 0x00},
  76.       {0x56, 0x00, 0x28},
  77.       {0xD6, 0x00, 0xC0},
  78.       {0xAF, 0x00, 0x4},
  79.    {0xF9, 0x00, 0x00}
  80.   };
  81.    
  82.   u8 EepromIicAddr;  /* Variable for storing Eeprom IIC address */
  83.    
  84.   int IicLowLevelDynEeprom();
  85.    
  86.   u8 EepromReadByte(AddressType Address, u8 *BufferPtr, u8 ByteCount);
  87.   u8 EepromWriteByte(AddressType Address, u8 *BufferPtr, u8 ByteCount);
  88.    
  89.    
  90.    
  91.   /****************i************ Type Definitions *******************************/
  92.    
  93.   typedef u8 AddressType;
  94.    
  95.   /************************** Variable Definitions *****************************/
  96.    
  97.   extern XIic IicFmc, IicAdapter ; /*  IIC device. */
  98.    
  99.   //HDMI IIC
  100.   int IicLowLevelDynEeprom()
  101.   {
  102.     u8 BytesRead;
  103.     u32 StatusReg;
  104.     u8 Index;
  105.     int Status;
  106.     u32 i;
  107.     EepromIicAddr = IIC_SWITCH_ADDRESS;
  108.     Status = XIic_DynInit(IIC_BASE_ADDRESS);
  109.     if (Status != XST_SUCCESS) {
  110.    return XST_FAILURE;
  111.     }
  112.     xil_printf("\r\nAfter XIic_DynInit\r\n");
  113.     while (((StatusReg = XIic_ReadReg(IIC_BASE_ADDRESS,
  114.       XIIC_SR_REG_OFFSET)) &
  115.       (XIIC_SR_RX_FIFO_EMPTY_MASK |
  116.       XIIC_SR_TX_FIFO_EMPTY_MASK |
  117.       XIIC_SR_BUS_BUSY_MASK)) !=
  118.       (XIIC_SR_RX_FIFO_EMPTY_MASK |
  119.       XIIC_SR_TX_FIFO_EMPTY_MASK)) {
  120.    
  121.     }
  122.    
  123.    
  124.     EepromIicAddr = IIC_ADV7511_ADDRESS;
  125.     for ( Index = 0; Index < NUMBER_OF_HDMI_REGS; Index++)
  126.     {
  127.       EepromWriteByte(hdmi_iic[Index].addr, &hdmi_iic[Index].init, 1);
  128.     }
  129.    
  130.     for ( Index = 0; Index < NUMBER_OF_HDMI_REGS; Index++)
  131.     {
  132.       BytesRead = EepromReadByte(hdmi_iic[Index].addr, &hdmi_iic[Index].data, 1);
  133.       for(i=0;i<1000;i++) {}; // IIC delay
  134.    if (BytesRead != 1) {
  135.         return XST_FAILURE;
  136.    }
  137.     }
  138.    
  139.    
  140.     return XST_SUCCESS;
  141.    
  142.   }
  143.    
  144.    
  145.   /*****************************************************************************/
  146.   /**
  147.   * This function writes a buffer of bytes to the IIC serial EEPROM.
  148.   *
  149.   * @param BufferPtr contains the address of the data to write.
  150.   * @param ByteCount contains the number of bytes in the buffer to be
  151.   *  written. Note that this should not exceed the page size of the
  152.   *  EEPROM as noted by the constant PAGE_SIZE.
  153.   *
  154.   * @return The number of bytes written, a value less than that which was
  155.   *  specified as an input indicates an error.
  156.   *
  157.   * @note  one.
  158.   *
  159.   ******************************************************************************/
  160.   u8 EepromWriteByte(AddressType Address, u8 *BufferPtr, u8 ByteCount)
  161.   {
  162.     u8 SentByteCount;
  163.     u8 WriteBuffer[sizeof(Address) + PAGE_SIZE];
  164.     u8 Index;
  165.    
  166.     /*
  167.      * A temporary write buffer must be used which contains both the address
  168.      * and the data to be written, put the address in first based upon the
  169.      * size of the address for the EEPROM
  170.      */
  171.     if (sizeof(AddressType) == 2) {
  172.    WriteBuffer[0] = (u8) (Address >> 8);
  173.    WriteBuffer[1] = (u8) (Address);
  174.     } else if (sizeof(AddressType) == 1) {
  175.    WriteBuffer[0] = (u8) (Address);
  176.    EepromIicAddr |= (EEPROM_TEST_START_ADDRESS >> 8) & 0x7;
  177.     }
  178.    
  179.     /*
  180.      * Put the data in the write buffer following the address.
  181.      */
  182.     for (Index = 0; Index < ByteCount; Index++) {
  183.    WriteBuffer[sizeof(Address) + Index] = BufferPtr[Index];
  184.     }
  185.    
  186.     /*
  187.      * Write a page of data at the specified address to the EEPROM.
  188.      */
  189.     SentByteCount = XIic_DynSend(IIC_BASE_ADDRESS, EepromIicAddr,
  190.       WriteBuffer, sizeof(Address) + ByteCount,
  191.       XIIC_STOP);
  192.    
  193.     /*
  194.      * Return the number of bytes written to the EEPROM.
  195.      */
  196.     return SentByteCount - sizeof(Address);
  197.    
  198.   }
  199.    
  200.    
  201.   /******************************************************************************
  202.   *
  203.   * This function reads a number of bytes from the IIC serial EEPROM into a
  204.   * specified buffer.
  205.   *
  206.   * @param BufferPtr contains the address of the data buffer to be filled.
  207.   * @param ByteCount contains the number of bytes in the buffer to be read.
  208.   *  This value is constrained by the page size of the device such
  209.   *  that up to 64K may be read in one call.
  210.   *
  211.   * @return The number of bytes read. A value less than the specified input
  212.   *  value indicates an error.
  213.   *
  214.   * @note  None.
  215.   *
  216.   ******************************************************************************/
  217.   u8 EepromReadByte(AddressType Address, u8 *BufferPtr, u8 ByteCount)
  218.   {
  219.     u8 ReceivedByteCount;
  220.     u8 SentByteCount;
  221.     u16 StatusReg;
  222.    
  223.     /*
  224.      * Position the Read pointer to specific location in the EEPROM.
  225.      */
  226.     do {
  227.    StatusReg = XIic_ReadReg(IIC_BASE_ADDRESS, XIIC_SR_REG_OFFSET);
  228.       if (!(StatusReg & XIIC_SR_BUS_BUSY_MASK)) {
  229.      SentByteCount = XIic_DynSend(IIC_BASE_ADDRESS, EepromIicAddr,
  230.          (u8 *) &Address, sizeof(Address), XIIC_REPEATED_START);
  231.       }
  232.    
  233.     } while (SentByteCount != sizeof(Address));
  234.     /*
  235.      * Receive the data.
  236.      */
  237.     ReceivedByteCount = XIic_DynRecv(IIC_BASE_ADDRESS, EepromIicAddr,
  238.                                               BufferPtr, ByteCount);
  239.    
  240.     /*
  241.      * Return the number of bytes received from the EEPROM.
  242.      */
  243.    
  244.     return ReceivedByteCount;
  245.    
  246.   }
  247.    
  248.    
  249.   /*****************************************************************************/
  250.   /**
  251.    *
  252.    * Main function to initialize interop system and read data from AR0330 sensor
  253.    
  254.    * @param  None.
  255.    *
  256.    * @return
  257.    *   - XST_SUCCESS if MIPI Interop was successful.
  258.    *   - XST_FAILURE if MIPI Interop failed.
  259.    *
  260.    * @note   None.
  261.    *
  262.    ******************************************************************************/
  263.   int main() {
  264.     int Status;
  265.     int pcam5c_mode = 1;
  266.     int usr_entry ,prev_sel;
  267.     int default_input;
  268.     int dsi_hdmi_select = 0;
  269.    
  270.     Xil_ICacheDisable();
  271.     Xil_DCacheDisable();
  272.     XAxis_Switch AxisSwitch;
  273.     XAxis_Switch_Config *ASWConfig;
  274.    
  275.     ASWConfig = XAxisScr_LookupConfig(XAXIS_SWITCH_DEVICE_ID);
  276.     XAxisScr_CfgInitialize(&AxisSwitch, ASWConfig,ASWConfig->BaseAddress);
  277.     XAxisScr_RegUpdateDisable(&AxisSwitch);
  278.     XAxisScr_MiPortDisableAll(&AxisSwitch);
  279.     XAxisScr_MiPortEnable(&AxisSwitch, 0, 0);
  280.     XAxisScr_RegUpdateEnable(&AxisSwitch);
  281.    
  282.     xil_printf("\n\r******************************************************\n\r");
  283.     xil_printf("\n\r**           SP701 Example Design            **");
  284.    
  285.     Status = IicLowLevelDynEeprom();
  286.     if (Status != XST_SUCCESS) {
  287.       xil_printf("ADV7511 IIC programming FAILED\r\n");
  288.       return XST_FAILURE;
  289.     }
  290.     xil_printf("ADV7511 IIC programming PASSED\r\n");
  291.    
  292.    
  293.     //Initialize FMC, Adapter and Sensor IIC
  294.     Status = InitIIC();
  295.     if (Status != XST_SUCCESS) {
  296.    xil_printf("\n\r IIC initialization Failed \n\r");
  297.    return XST_FAILURE;
  298.     }
  299.     xil_printf("IIC Initializtion Done \n\r");
  300.    
  301.     //Initialize FMC Interrupt System
  302.     Status = SetupFmcInterruptSystem(&IicFmc);
  303.     if (Status != XST_SUCCESS) {
  304.       xil_printf("\n\rInterrupt System Initialization Failed \n\r");
  305.       return XST_FAILURE;
  306.     }
  307.     xil_printf("FMC Interrupt System Initialization Done \n\r");
  308.    
  309.     //Set up IIC Interrupt Handlers
  310.     SetupIICIntrHandlers();
  311.     xil_printf("IIC Interrupt Handlers Setup Done \n\r");
  312.    
  313.     Status =  SetFmcIICAddress();
  314.     if (Status != XST_SUCCESS) {
  315.       xil_printf("\n\rFMC IIC Address Setup Failed \n\r");
  316.    return XST_FAILURE;
  317.     }
  318.     xil_printf("Fmc IIC Address Set\n\r");
  319.    
  320.     //Initialize Adapter Interrupt System
  321.     Status = SetupAdapterInterruptSystem(&IicAdapter);
  322.     if (Status != XST_SUCCESS) {
  323.       xil_printf("\n\rInterrupt System Initialization Failed \n\r");
  324.       return XST_FAILURE;
  325.     }
  326.     xil_printf("Adapter Interrupt System Initialization Done \n\r");
  327.    
  328.     //Set Address of Adapter IIC
  329.     Status =  SetAdapterIICAddress();
  330.     if (Status != XST_SUCCESS) {
  331.       xil_printf("\n\rAdapter IIC Address Setup Failed \n\r");
  332.    return XST_FAILURE;
  333.     }
  334.     xil_printf("Adapter IIC Address Set\n\r");
  335.    
  336.     Status = InitializeCsiRxSs();
  337.     if (Status != XST_SUCCESS) {
  338.       xil_printf("CSI Rx Ss Init failed status = %x.\r\n", Status);
  339.    return XST_FAILURE;
  340.     }
  341.    
  342.    
  343.     dsi_hdmi_select = 0;
  344.     //using default_input var to compare same option selection
  345.     default_input = 1;
  346.     //SetupDSI();
  347.     resetIp();
  348.     EnableCSI();
  349.     GPIOSelect(dsi_hdmi_select);
  350.    
  351.     Status = demosaic();
  352.     if (Status != XST_SUCCESS) {
  353.    xil_printf("\n\rDemosaic Failed \n\r");
  354.    return XST_FAILURE;
  355.     }
  356.    
  357.     CamReset();
  358.    
  359.     //Preconifgure Sensor
  360.     Status = SensorPreConfig(pcam5c_mode);
  361.     if (Status != XST_SUCCESS) {
  362.    xil_printf("\n\rSensor PreConfiguration Failed \n\r");
  363.    return XST_FAILURE;
  364.     }
  365.     xil_printf("\n\rSensor 1 is PreConfigured\n\r");
  366.     WritetoReg(0x30, 0x08, 0x02);
  367.    
  368.     //Preconifgure Sensor
  369.     Status = SensorPreConfig1(pcam5c_mode);
  370.     if (Status != XST_SUCCESS) {
  371.    xil_printf("\n\rSensor PreConfiguration Failed \n\r");
  372.    return XST_FAILURE;
  373.     }
  374.     xil_printf("\n\rSensor 2 is PreConfigured\n\r");
  375.     WritetoReg(0x30, 0x08, 0x02);
  376.    
  377.    
  378.     Status = vdma_hdmi();
  379.     if (Status != XST_SUCCESS) {
  380.       xil_printf("\n\rVdma_hdmi Failed \n\r");
  381.    return XST_FAILURE;
  382.     }
  383.    
  384.     Status = vtpg_hdmi();
  385.     if (Status != XST_SUCCESS) {
  386.       xil_printf("\n\rVtpg Failed \n\r");
  387.    return XST_FAILURE;
  388.     }
  389.    
  390.    
  391.     Sensor_Delay();
  392.     xil_printf("\n\rPipeline Configuration Completed \n\r");
  393.    
  394.     while(1) {
  395.    
  396.       xil_printf("\r\nPlease Select Camera(1 or 2) + ENTER:");
  397.    
  398.    
  399.       usr_entry = getchar();
  400.    
  401.      char b;
  402.      scanf("%c", &b);// This will take ENTER key
  403.    
  404.    
  405.    
  406.    switch(usr_entry) {
  407.    
  408.      case '1':
  409.       xil_printf("\n\rSwitching to Camera 1\n\r");
  410.       XAxisScr_RegUpdateDisable(&AxisSwitch);
  411.       XAxisScr_MiPortDisableAll(&AxisSwitch);
  412.       XAxisScr_MiPortEnable(&AxisSwitch, 0, 0);
  413.       XAxisScr_RegUpdateEnable(&AxisSwitch);
  414.       break;
  415.    
  416.      case '2':
  417.       xil_printf("\n\rSwitching to Camera 1\n\r");
  418.       XAxisScr_RegUpdateDisable(&AxisSwitch);
  419.       XAxisScr_MiPortDisableAll(&AxisSwitch);
  420.       XAxisScr_MiPortEnable(&AxisSwitch, 0, 1);
  421.       XAxisScr_RegUpdateEnable(&AxisSwitch);
  422.       break;
  423.    
  424.      default:
  425.       xil_printf("\n\rSelection is unavailable. Please try again\n\r");
  426.       break;
  427.    }
  428.    
  429.     }
  430.     return XST_SUCCESS;
  431.    
  432.   }

测试

我们可以在连接到 HDMI 输出时运行应用程序并在显示器上看到图像。

使用应用程序选择图像。

b851c7966964f01c2eff4078ac911dc3.png b56c09adfdc6dc681b8aff2b56b653e0.png 0f7e235ca85af8061114d92f408c2990.png 252799c7f032ded356a564094a4859a6.png

参考

https://www.hackster.io/

总结

该项目展示了一个MIPI摄像头接入FPGA的简单、快捷的方式,同时可以学习一下软件的导入工程的方式,简单的基于MicroBlaze系统要学会自己写控制代码,也许这就是新一代“FPGA打工人”需要掌握的一项新技术吧~(doge~不是)

5af13d168e1d5dcc549eb713b9f04a0a.png

示例工程

https://github.com/ATaylorCEngFIET/Hackster/tree/master

https://github.com/ATaylorCEngFIET/SP701_Imaging_Vivado

标签:Status,MIPI,return,u8,XST,printf,xil,图像,摄像头
From: https://www.cnblogs.com/kn-zheng/p/17167227.html

相关文章

  • 全志 芯片 Linux MIPI CSI摄像头接口开发指南 VIN DVP CSI MIPI V4l2
    1前言1.1文档简介介绍VIN(videoinput)驱动配置,API接口和上层使用方法。1.2目标读者camera驱动开发、维护人员和应用开发人员。1.3适用范围​表1-1:适用产品......
  • 深入分析MobileAI图像超分最佳方案:ABPN
    前言 本文设计一种8-bit量化版高效网络并将其部署到移动端,旨在构建一种实时量化模型用于真实场景(比如实时视频超分)。本文转载自AIWalker来源|HappyAIWalker欢迎关......
  • DataTransfer.setDragImage()自定义拖拽图像遇到的坑
    发生拖动时,从拖动目标(dragstart事件触发的元素)生成半透明图像,并在拖动过程中跟随鼠标指针。这个图片是自动创建的,你不需要自己去创建它。然而,如果想要设置为自定义图像,那......
  • 基于PCNN脉冲耦合神经网络的图像分割
    1.算法描述       脉冲耦合神经网络(PCNN-PulseCoupledNeuralNetwork)与传统神经网络相比,有着根本的不同。PCNN有生物学的背景,它是依据猫、猴等动物的大脑皮层上......
  • 现代图片性能优化及体验优化指南 - 懒加载及异步图像解码方案
    本文是系列第四篇。系列文章:现代图片性能优化及体验优化指南-图片类型及Picture标签的使用现代图片性能优化及体验优化指南-响应式图片方案现代图片性能优化及体......
  • 积分图像
    符号说明I(x,y)为积分值,i(x,y)为像素值一.问题的引入原图像  积分图像积分图像是怎样由原图像得来得呢?例如第第二行第一列的像素的积分值为I(2,1)=i(1,1)+i(2,1)=......
  • C#绘制带控制点的Bezier曲线,用于点阵图像及矢量图形
    【摘要】不借助第三方,使用c#+GDI+进行SVG等绘图,绘制带控制点的Bezier曲线。可用于点阵图像及矢量图形(如SVG)绘图。///<summary>///Bezier样条曲线///</summary>p......
  • python用turtle画出给定图片的图像
    python用turtle画出给定图片的图像、校徽等复杂图像都可以需要:1.要画的图片2.安装好cv和turtle打开python文件,把想画的图片放到和py文件同目录,代码中默认图片名字为1.xxxxx......
  • 瑞芯微平台MIPI摄像头应用程序编写
    前面3篇我们讲解了camera的基础概念,MIPI协议,CSI2,常用命令等,本文带领大家入门,如何用c语言编写应用程序来操作摄像头。Linux下摄像头驱动都是基于v4l2架构,要基于该架构编写......
  • OpenCvSharp裁剪图像、寻找圆心
    裁剪图像OpenCvSharp.Rectrect=newOpenCvSharp.Rect(4800,2100,400,900);//设置范围OpenCvSharp.Matcropped_image=newOpenCvShar......