Gd32450i Eval learning notes 17 - digital camera interface (DCI)

catalogue

1 IO initialization

2 initialize DCI

2.1 enable DCI and DMA1

2.2 configuration register DCI_CTL

2.2.1 snapshot mode SNAP

2.2.2 clock polarity selection CKS

2.2.3   Horizontal synchronous polarity selection HPS

2.2.4   Vertical synchronous polarity selection VPS

2.2.5   Data format DCIF

2.2.6   Frame frequency FR

2.3 configuring DMA

3. Enable DCI

4. Initialize OV2640

5. Set the pixel size of OV2640

6. Initialize the camera

The digital camera interface is a synchronous parallel interface, which can capture video and image information from the digital camera. It supports different
Color space images, such as YUV/RGB, also support JPEG format images of compressed data.

1 IO initialization

  DCI generally selects 8bit interface. In addition, OV2640 requires I2C interface setting register.

2 initialize DCI

2.1 enable DCI and DMA1

RCU_AHB2EN |= ((uint32_t)1 << 0);  //Enable DCI
RCU_AHB1EN |= ((uint32_t)1 << 22);  //Enable DMA1

Generally, DMA function is used when DCI is used. DCI corresponds to channel 1 or channel 7 of DMA1. Channel 7 is used here

2.2 configuration register DCI_CTL

2.2.1 snapshot mode SNAP

0: continuous capture mode - continuous capture of camera data

1: Snapshot mode-   Only a single frame is captured. After receiving the complete first frame, the camera interface will be automatically disabled

2.2.2 clock polarity selection CKS

0: falling edge capture

1: Rising edge capture

2.2.3   Horizontal synchronous polarity selection HPS

0: low level during blanking

1: Blanking period high level

2.2.4   Vertical synchronous polarity selection VPS

0: low level during blanking

1: Blanking period high level

2.2.5   Data format DCIF

00: each pixel clock captures 8 bits of data

01: capture 10 bits of data per pixel clock

10: Each pixel clock captures 12 bits of data

11: Each pixel clock captures 14 bits of data

It is generally set to 8-bit data

2.2.6   Frame frequency FR

In the continuous capture mode, FR defines the frame capture frequency

00: capture all frames

01: capture every other frame

10: Capture every three frames

11: Reserved

2.3 configuring DMA

Two DMA channels can be used for DCI, i.e. channel 1 and channel 7 of DMA1

    DMA_CHFCTL(DMA1, CAMERA_DMA_CH) = 0;
    DMA_CHCTL(DMA1, CAMERA_DMA_CH) = 0;
    
    DMA_CHFCTL(DMA1, CAMERA_DMA_CH) &= ~((uint32_t)1 << 2); //Disable Multi Data Mode
    DMA_CHPADDR(DMA1, CAMERA_DMA_CH) = (uint32_t)&DCI_DATA;
    DMA_CHM0ADDR(DMA1, CAMERA_DMA_CH) = ramAddr;
    DMA_CHCNT(DMA1, CAMERA_DMA_CH) = (uint32_t)CAMERA_SIZE_W * CAMERA_SIZE_H * stride / 4;
    
    value = DMA_CHCTL(DMA1, CAMERA_DMA_CH);
    //bit6-7: channel transfer mode
    //bit11-12: transfer data width of peripheral
    //bit13-14: transfer data width of memory
    //bit16-17: channel priority level
    value &= ~((uint32_t)0x03 << 11 | ((uint32_t)3 << 13) | ((uint32_t)3 << 16) | ((uint32_t)3 << 6));
    value |= (((uint32_t)2 << 11) | ((uint32_t)2 << 13) | ((uint32_t)2 << 16) | ((uint32_t)0 << 6));
    //bit9: next address generation algorithm of peripheral
    value &= ~((uint32_t)1 << 9); //Disable Peripheral's Address Auto Increasing.
    //bit10: next address generation algorithm of memory
    value |= ((uint32_t)1 << 10);        //Enable Memory's Address Auto Increasing.
    //bit8: DMA circular mode
    value |= ((uint32_t)1 << 8);        //Enable DMA Circular Mode
    //bit25-27: peripheral enable
    value &= ~((uint32_t)0x7 << 25);
    value |= ((uint32_t)0x1 << 25); //Peripheral 1(DCI is 1) is enable.
    
    DMA_CHCTL(DMA1, CAMERA_DMA_CH) = value;

ramAddr is the RAM space allocated to DCI in MCU. For example, here is an array

#define CAMERA_SIZE_W                   320
#define CAMERA_SIZE_H                   240
EXTERN uint16_t gCameraBuf[CAMERA_SIZE_W * CAMERA_SIZE_H];

The camera adopts RGB565 format, and one pixel corresponds to two bytes, so uint16 is used here_ T defines this array variable, corresponding to stripe = 2 (that is, RGB565 is 2 bytes).

2.4 configure clock output

    reg = RCU_CFG0;
    #if (PIN_DCI_XCLK == 8)
    /* reset the CKOUT0SRC, CKOUT0DIV and set according to ckout0_src and ckout0_div */
    reg &= ~(RCU_CFG0_CKOUT0SEL | RCU_CFG0_CKOUT0DIV);
    RCU_CFG0 = (reg | RCU_CKOUT0SRC_HXTAL | RCU_CKOUT0_DIV3);
    #else
    reg &= ~(RCU_CFG0_CKOUT1SEL | RCU_CFG0_CKOUT1DIV);
    RCU_CFG0 = (reg | RCU_CKOUT1SRC_HXTAL | RCU_CKOUT1_DIV3);
    #endif

3. Enable DCI

void dciEnable(void)
{
    DMA_CHCTL(DMA1, CAMERA_DMA_CH) |= ((uint32_t)1 << 0 | ((uint32_t)0x1 << 4)); //DMA_ENABLE
    DCI_CTL |= ((uint32_t)1 << 14);    //DCI enable
    DCI_CTL |= ((uint32_t)1 << 0);            //DCI capture enable
}

It mainly enables DMA and DCI.

4. Initialize OV2640

void ov2640Init(void)
{
    uint8_t buf[1];
    uint16_t i;
    bool_t status = 0;
    /* OV2640 reset */
    buf[0] = 0x01;
    status = i2cWrite(I2C_CAMERA, OV2640_ADDRESS, 8, 0xff, buf, 1);
    if(status == FALSE)
    {
        OV2640_INFO(Printf("ov2640 init fail 1\n"));
    }
    buf[0] = 0x80;
    status = i2cWrite(I2C_CAMERA, OV2640_ADDRESS, 8, 0x12, buf, 1);
    if(status == FALSE)
    {
        OV2640_INFO(Printf("ov2640 init fail 2\n"));
    }
    delayms(10);
    for(i = 0; i < sizeof(ov2640_svga_init_reg_tbl) / 2; i++)
    {
        status = i2cWrite(I2C_CAMERA, OV2640_ADDRESS, 8, ov2640_svga_init_reg_tbl[i][0], (uint8_t *)&(ov2640_svga_init_reg_tbl[i][1]), 1);
        if(status == FALSE)
        {
            OV2640_INFO(Printf("ov2640 init fail 3:%d\n", i));
            break;
        }
    }
    delayms(100);
    for(i = 0; i < sizeof(ov2640_rgb565_reg_tbl)/2; i++)
    {
        status = i2cWrite(I2C_CAMERA, OV2640_ADDRESS, 8, ov2640_rgb565_reg_tbl[i][0], (uint8_t *)&(ov2640_rgb565_reg_tbl[i][1]), 1);
        if(status == FALSE)
        {
            OV2640_INFO(Printf("ov2640 init fail 4:%d\n", i));
            break;
        }
    }
    delayms(100);
}

5. Set the pixel size of OV2640

The pixel size of OV2640 must be 4 multiples

void ov2640SetSize(uint16_t w, uint16_t h)
{
    uint16_t outh;
    uint16_t outw;
    uint8_t buf[1];
    
    if((w % 4) > 0)
        return;
    if((h % 4) > 0)
        return;

    outw = w / 4;
    outh = h / 4;
    buf[0] = 0x00;  
    i2cWrite(I2C_CAMERA, OV2640_ADDRESS, 8, 0xff, buf, 1);
    buf[0] = 0x04;  
    i2cWrite(I2C_CAMERA, OV2640_ADDRESS, 8, 0xE0, buf, 1);
    buf[0] = outw & 0xFF;  
    i2cWrite(I2C_CAMERA, OV2640_ADDRESS, 8, 0x5A, buf, 1);
    buf[0] = outh & 0xFF;  
    i2cWrite(I2C_CAMERA, OV2640_ADDRESS, 8, 0x5B, buf, 1);

    buf[0] = (outw >> 8) & 0x03;
    buf[0] |= (outh >> 6) & 0x04;
    i2cWrite(I2C_CAMERA, OV2640_ADDRESS, 8, 0x5C, buf, 1); 
    
    buf[0] = 0x00;  
    i2cWrite(I2C_CAMERA, OV2640_ADDRESS, 8, 0xE0, buf, 1);
}

6. Initialize the camera

Finally, the content of the camera is displayed on the TFT screen, so the data needs to be displayed on the TLI.

    tliLayer_t layer;
    ov2640Init();
    Printf("OV2640 ID:%x\n", ov2640GetID());
    ov2640SetSize(CAMERA_SIZE_W, CAMERA_SIZE_H);
    dciEnable();
    delayms(100);
    layer.alpha = 0xFF;
    layer.bufAddr = (uint32_t)gCameraBuf;//(uint32_t)0xC0000000;
    layer.defalutColor = 0x00FFFFFF;
    layer.format = FORMAT_RGB565;
    layer.x = 0;
    layer.y = 0;
    layer.w = CAMERA_SIZE_W;
    layer.h = CAMERA_SIZE_H;
    tliLayerInit(0, layer, 1);

Tags: stm32

Posted on Tue, 26 Oct 2021 05:34:17 -0400 by moonman89