608 views|3 replies

445

Posts

0

Resources
The OP
 

【GigaDevice GD32H759I-EVAL】--9. Camera display [Copy link]

 
This post was last edited by dirty on 2024-6-1 19:56

This article describes the camera driver and displays it on the LCD screen.

1. Understand the principle of camera

The development board is equipped with an OV2640 camera, DVP interface, 2 million pixels. The principle of the development board camera is as follows.

Figure 1: Camera principle

Pin function definition:

PIXCLK output clock
XCLK external clock input
VSYNC field synchronization
HSYNC line synchronization
D[0:7] parallel port data (8 bit data bit size)

I2C interface: register driver configuration

Module features:

Standard SCCB interface, compatible with I2C interface:
RaWRGB, RGB (GRB4:2:2, RGB565/555/444), YUV (4:2:2) and YCbCr (4:2:2) output formats.
Support UXGA, SXGA, VGA, QVGA, QQVGA, CIF, QCIF, etc. Support automatic exposure control, automatic gain control, automatic white balance, automatic elimination of light stripes, automatic black level calibration. Image quality control includes color saturation, hue, gamma, sharpness ANTI BLOOM and other settings.
Support image zoom, pan and window settings.
Support image compression, that is, output JPEG image data.

2. Software Code

Implementation method: Use the DCI interface to collect data, and use the TLI interface used previously to display the collected image. Here, based on the previous LVGL project, the button is used to switch the camera image to the LCD screen.

1. Add the source file of the camera driver in the SDK, as shown below

Figure 2: Adding camera driver files

2. Camera driver initialization. Here, the camera sccb pin and dci configuration are initialized, including I2C initialization and DMA initialization. Then the camera is configured by writing parameters. Finally, the camera output image size is defined as 320*240. The display screen is 480*272, so conversion is involved later.

/*!
    \brief      DCI camera initialization
    \param[in]  none
    \param[out] none
    \retval     0x00 or 0xFF
*/
uint8_t dci_ov2640_init(void)
{
    uint8_t i;
    sccb_config();
    dci_config();
    
    ckout0_init();
    delay_1ms(100);
    /* OV2640 reset */
    if(dci_byte_write(0xFF, 0x01) != 0) {
        return 0xFF;
    }
    if(dci_byte_write(0x12, 0x80) != 0) {
        return 0xFF;
    }
    delay_1ms(10);
    for(i = 0; i < sizeof(ov2640_svga_init_reg_tbl) / 2; i++) {
        if(0 != dci_byte_write(ov2640_svga_init_reg_tbl[i][0], ov2640_svga_init_reg_tbl[i][1])) {
            return 0xFF;
        }
    }

    delay_1ms(100);
    for(i = 0; i < (sizeof(ov2640_rgb565_reg_tbl) / 2); i++) {
        if(0 != dci_byte_write(ov2640_rgb565_reg_tbl[i][0], ov2640_rgb565_reg_tbl[i][1])) {
            return 0xFF;
        }
    }
    delay_1ms(100);
    ov2640_outsize_set(320, 240);
    return 0;
}

3. Read the camera information, including manufacturer, version and pid.

/*!
    \brief      read the ov2640 manufacturer identifier
    \param[in]  ov2640id: pointer to the ov2640 manufacturer struct
    \param[out] none
    \retval     0x00 or 0xFF
*/
uint8_t dci_ov2640_id_read(ov2640_id_struct *ov2640id)
{
    uint8_t temp;
    dci_byte_write(0xFF, 0x01);
    if(dci_byte_read(OV2640_MIDH, &temp) != 0) {
        return 0xFF;
    }
    ov2640id->manufacturer_id1 = temp;
    if(dci_byte_read(OV2640_MIDL, &temp) != 0) {
        return 0xFF;
    }
    ov2640id->manufacturer_id2 = temp;
    if(dci_byte_read(OV2640_VER, &temp) != 0) {
        return 0xFF;
    }
    ov2640id->version = temp;
    if(dci_byte_read(OV2640_PID, &temp) != 0) {
        return 0xFF;
    }
    ov2640id->pid = temp;

    return 0x00;
}

4. Configure DMA and DCI. Here, LVGL is displayed on LAYER0 and the camera image is displayed on LAYER1, so disable the camera first.

    nvic_configuration();

    /* DMA interrupt and channel enable */
    dma_interrupt_enable(DMA1, DMA_CH7, DMA_CHXCTL_FTFIE);
    dma_channel_enable(DMA1, DMA_CH7);
    /* DCI enable */
    dci_enable();
    dci_capture_enable();
    delay_1ms(3000);

    dma_interrupt_disable(DMA1, DMA_CH7, DMA_CHXCTL_FTFIE);
    dma_channel_disable(DMA1, DMA_CH7);
    dci_capture_disable();

5. The captured photo data is saved to SDRAM. The video stream is not stopped here. If you want to take a photo, you can open the shield.

/*!
    \brief      save image to sdram
    \param[in]  none
    \param[out] none
    \retval     none
*/
void image_save(void)
{
    uint32_t i = 0;

    // dma_interrupt_disable(DMA1, DMA_CH7, DMA_CHXCTL_FTFIE);
    // dma_channel_disable(DMA1, DMA_CH7);
    // dci_capture_disable();

    /* save image to sdram */
    for(i = 0; i < 32640; i++) {
        *(uint32_t *)(0xC0800000 + 4 * i) = *(uint32_t *)(0xC1000000 + 4 * i);
    }
}

6. Camera image display, switch layers here.

/*!
    \brief      display image to lcd
    \param[in]  display_image_addr: image display address
    \param[out] none
    \retval     none
*/
void image_display(uint32_t display_image_addr)
{

    tli_layer_parameter_struct         tli_layer1_initstruct;

    /* input address configuration */
    tli_layer1_initstruct.layer_frame_bufaddr = (uint32_t)display_image_addr;

    /* layer1 windowing configuration */
    tli_layer1_initstruct.layer_window_leftpos = 162;
    tli_layer1_initstruct.layer_window_rightpos = (160 + 240 - 1);
    tli_layer1_initstruct.layer_window_toppos =  12;
    tli_layer1_initstruct.layer_window_bottompos = (12 + 272 - 1);

    /* pixel format configuration */
    tli_layer1_initstruct.layer_ppf = LAYER_PPF_RGB565;

    /* alpha constant configuration : the constant alpha for layer 1 is decreased
    to see the layer 0 in the intersection zone*/
    tli_layer1_initstruct.layer_sa = 255;

    /* default color configuration (configure A,R,G,B component values) */
    tli_layer1_initstruct.layer_default_blue = 0xFF;
    tli_layer1_initstruct.layer_default_green = 0xFF;
    tli_layer1_initstruct.layer_default_red = 0xFF;
    tli_layer1_initstruct.layer_default_alpha = 0;

    /* blending factors */
    tli_layer1_initstruct.layer_acf1 = LAYER_ACF1_PASA;
    tli_layer1_initstruct.layer_acf2 = LAYER_ACF1_PASA;

    // /* configure input address : frame buffer is located at memory */
    // tli_layer1_initstruct.layer_frame_bufaddr = (uint32_t)0xC1000000;

    tli_layer1_initstruct.layer_frame_line_length = ((240 * 2) + 3);
    tli_layer1_initstruct.layer_frame_buf_stride_offset = (240 * 2);

    tli_layer1_initstruct.layer_frame_total_line_number = 272;

    tli_layer_init(LAYER1, &tli_layer1_initstruct);
    tli_dither_config(TLI_DITHER_ENABLE);

    tli_layer_init(LAYER1, &tli_layer1_initstruct);

    /* disenable layer0 */
    tli_layer_disable(LAYER0);
    /* enable layer1 */
    tli_layer_enable(LAYER1);
    /* reload configuration */
    tli_reload_config(TLI_REQUEST_RELOAD_EN);

    /* enable TLI */
    tli_enable();
}

7. Add interrupt handling function in Project\gd32h7xx_it.c. EXTI10_15_IRQHandler is Tamper key interrupt, saves photo data and enables DMA1 and turns on camera DCI capture. DMA1_Channel7_IRQHandler processes data and converts 320*240 camera data into 240*272 screen display data.

/*!
    \brief      this function handles external lines 10 to 15 interrupt request
    \param[in]  none
    \param[out] none
    \retval     none
*/
void EXTI10_15_IRQHandler(void)
{

    if(RESET != exti_interrupt_flag_get(EXTI_13)) 
    {
        printf("Key Pressed\r\n");
        exti_interrupt_flag_clear(EXTI_13); 
        
        dma_interrupt_enable(DMA1, DMA_CH7, DMA_CHXCTL_FTFIE);
        dma_channel_enable(DMA1, DMA_CH7);
        dci_capture_enable();
        
        image_save();
        image_display((uint32_t)image_background1);
        delay_1ms(500);
        image_display((uint32_t)0XC1000000);
        //lv_demo_music(); 
             
    }
}


/*!
    \brief      this function handles DMA1_Channel7_IRQ interrupt request
    \param[in]  none
    \param[out] none
    \retval     none
*/
void DMA1_Channel7_IRQHandler(void)
{
    /* 320*240 size image convert to 240*272 size image */
    if(dma_interrupt_flag_get(DMA1, DMA_CH7, DMA_INT_FLAG_FTF)) 
    {
        //printf("\r\nprocess image\r\n");
        int i = 0, x = 0, y = 0;
        dma_channel_disable(DMA1, DMA_CH7);
        
        for(x = 0; x < 320; x++) {
            for(y = 0; y < 240; y++) {
                if(x < 272) {
                    *(uint16_t *)(0xC1000000 + 2 * i) = *(uint16_t *)(0xC0000000 + 2 * ((320 * y) + x));
                    i++;
                }
            }
        }
        dma_interrupt_flag_clear(DMA1, DMA_CH7, DMA_INT_FLAG_FTF);
        dma_channel_enable(DMA1, DMA_CH7);
    }
}

8.main function

int main(void)
{
    ov2640_id_struct ov2640id;
    BaseType_t ret;
    
    /* enable the CPU cache */
    cache_enable();
    /* initialize the LEDs */
    test_status_led_init();

    /* configure systick */
    systick_config();
    
   

    /* flash the LEDs for 2 time */
    led_flash(2);

    /* configure USART0 */
    usart_config();

    /* configure TAMPER key */
    gd_eval_key_init(KEY_TAMPER, KEY_MODE_EXTI);

    /* output a message on hyperterminal using printf function */
    printf("\r\n =================  LVGL =================   \r\n");

    /**********************LCD Application**********************/
    
    /* config the EXMC access mode */
    exmc_synchronous_dynamic_ram_init(EXMC_SDRAM_DEVICE0);
    printf("\r\nSDRAM Init \r\n");

    /* camera initialization */
    dci_ov2640_init();
    dci_ov2640_id_read(&ov2640id);
    printf("\r\nMF1:0x%02x,MF2:0x%02x,version:0x%02x,pid:0x%02x\r\n",ov2640id.manufacturer_id1,\
        ov2640id.manufacturer_id2,ov2640id.version,ov2640id.pid);

    nvic_configuration();

    /* DMA interrupt and channel enable */
    dma_interrupt_enable(DMA1, DMA_CH7, DMA_CHXCTL_FTFIE);
    dma_channel_enable(DMA1, DMA_CH7);
    /* DCI enable */
    dci_enable();
    dci_capture_enable();
    delay_1ms(100);

    dma_interrupt_disable(DMA1, DMA_CH7, DMA_CHXCTL_FTFIE);
    dma_channel_disable(DMA1, DMA_CH7);
    dci_capture_disable();


    timer_config();
    
    lcd_config();
    lcd_init();
    /* configure the GPIO of SPI touch panel */
    touch_panel_gpio_configure();
    #if (LVGL_DMA)
    delay_1ms(50);
    dma_config();
    delay_1ms(1000);
    #endif

    lv_init();
    lv_port_disp_init();
    lv_port_indev_init();

    // lv_demo_music();
    lv_demo_widgets();

    while(1)
    {
        delay_1ms(5);
        lv_task_handler();
    }
    
}

3. Test

After compiling and burning, you can see the LCD display widgets. After pressing the Tamper button, the screen creates a 240*272 camera video display. See the video for the effect. The imaging effect is average. You can adjust the ov2640_svga_init_reg_tbl register parameters for optimization.

At this point, the camera image screen display is realized.

camera_show

This post is from Domestic Chip Exchange

Latest reply

[attach]813690[/attach] Camera image display is OK   Details Published on 2024-6-4 07:33
 
 

445

Posts

0

Resources
From 4
 
This post was last edited by dirty on 2024-6-24 23:38

Camera screen display engineering code

FreeRTOS_LVGL_Camera.rar

36.76 MB, downloads: 3

摄像头屏显工程

This post is from Domestic Chip Exchange
 
 
 

6570

Posts

0

Resources
2
 

Camera image display is OK

This post is from Domestic Chip Exchange

Comments

Yes, it's done.  Details Published on 2024-6-12 09:17
 
 
 

445

Posts

0

Resources
3
 
Jacktang posted on 2024-6-4 07:33 The camera image screen display is OK

Yes, it's done.

This post is from Domestic Chip Exchange
 
 
 

Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list