Sample of NTSC 2ch input.

Dependencies:   GR-PEACH_video LCD_shield_config

概要

2系統のNTSC入力をLCDの左右に分けて表示するサンプルです。
ハードウエア機能を用いることで起動時にビデオ入力とLCD出力の設定した後は自動で動作し続けます。そのため、起動後のCPU負荷が少ないのが特徴です。

機能設定

下記のマクロを変更することで、一部機能を変更できます。

main.cpp

/**** User Selection *********/
/** Camera setting **/
#define VIDEO_INPUT_FORMAT     (VIDEO_YCBCR422)    /* Select  VIDEO_YCBCR422 or VIDEO_RGB888 or VIDEO_RGB565        */
#define VIDEO_PAL              (0)                 /* Select  0(NTSC) or 1(PAL) If selecting VIDEO_CVBS, this parameter is not referenced.) */
/** LCD setting **/
#define LCD_TYPE               (0)                 /* Select  0(4.3inch) or 1(7.1inch) */
/*****************************/


VIDEO_INPUT_FORMATVIDEO_YCBCR422、VIDEO_RGB888、VIDEO_RGB565から選択できます。
VIDEO_PAL0を設定するとNTSC、1を設定するとPALの設定となります。
LCD_TYPE0を設定するとGR-PEACH 4.3 inch LCD Shield、1を設定するとGR-PEACH 7.1 inch LCD Shieldの設定となります。


また、下記関数の引数を変更することで、入力画像の表示位置や大きさを変更できます。
(Output bufferの範囲を超えるような値は設定しないでください。幅は16の倍数、高さは8の倍数を設定してください。)

main.cpp main()

    /* Start of Video ch0 */
    Start_Video(
        DisplayBase::VIDEO_INPUT_CHANNEL_0,   /* Video input channe */
        user_frame_buffer0,                   /* Output buffer */
        0,                                    /* The x coordinate of the upper-left corner */
        0,                                    /* The y coordinate of the upper-left corner */
        (LCD_PIXEL_WIDTH / 2),                /* width  (A multiple of 16) */
        LCD_PIXEL_HEIGHT                      /* height (A multiple of 8) */
    );

(上記の例はNTSC1Aの入力をLCDの画面左側に表示するための設定です。入力画像の高さはLCD画面サイズと同じ、幅は画面サイズの1/2に設定しています。)

構成

GR-PEACHGR-PEACH 4.3 inch LCD Shield または GR-PEACH 7.1 inch LCD ShieldGR-PEACH AUDIO CAMERA Shield

GR-PEACH AUDIO CAMERA Shieldを使用しない場合は、NTSC1Aピン、および、NTSC1Bピンにアナログ信号を入力してください。 /media/uploads/dkato/video_display_analog.jpg
(写真はNTSC1Aピン(黄色)とGNDピン(黒)を引き出した例です。)

main.cpp

Committer:
dkato
Date:
2016-11-25
Revision:
2:d04ef6b5cb70
Parent:
1:e59e938472ac

File content as of revision 2:d04ef6b5cb70:

#include "mbed.h"
#include "DisplayBace.h"
#include "rtos.h"

#define VIDEO_YCBCR422         (0)
#define VIDEO_RGB888           (1)
#define VIDEO_RGB565           (2)

/**** User Selection *********/
/** Camera setting **/
#define VIDEO_INPUT_FORMAT     (VIDEO_YCBCR422)    /* Select  VIDEO_YCBCR422 or VIDEO_RGB888 or VIDEO_RGB565        */
#define VIDEO_PAL              (0)                 /* Select  0(NTSC) or 1(PAL) If selecting VIDEO_CVBS, this parameter is not referenced.) */
/** LCD setting **/
#define LCD_TYPE               (0)                 /* Select  0(4.3inch) or 1(7.1inch) */
/*****************************/

/** LCD shield config **/
#if (LCD_TYPE == 0)
  #include "LCD_shield_config_4_3inch.h"
#else
  #include "LCD_shield_config_7_1inch.h"
#endif

/** Video and Grapics (GRAPHICS_LAYER_0) parameter **/
/* NTSC or PAL */
#if VIDEO_PAL == 0
  #define COL_SYS              (DisplayBase::COL_SYS_NTSC_358)
#else
  #define COL_SYS              (DisplayBase::COL_SYS_PAL_443)
#endif

/* Video input and LCD layer 0 output */
#if VIDEO_INPUT_FORMAT == VIDEO_YCBCR422
  #define VIDEO_FORMAT         (DisplayBase::VIDEO_FORMAT_YCBCR422)
  #define GRAPHICS_FORMAT      (DisplayBase::GRAPHICS_FORMAT_YCBCR422)
  #define WR_RD_WRSWA          (DisplayBase::WR_RD_WRSWA_NON)
#elif VIDEO_INPUT_FORMAT == VIDEO_RGB565
  #define VIDEO_FORMAT         (DisplayBase::VIDEO_FORMAT_RGB565)
  #define GRAPHICS_FORMAT      (DisplayBase::GRAPHICS_FORMAT_RGB565)
  #define WR_RD_WRSWA          (DisplayBase::WR_RD_WRSWA_32_16BIT)
#else
  #define VIDEO_FORMAT         (DisplayBase::VIDEO_FORMAT_RGB888)
  #define GRAPHICS_FORMAT      (DisplayBase::GRAPHICS_FORMAT_RGB888)
  #define WR_RD_WRSWA          (DisplayBase::WR_RD_WRSWA_32BIT)
#endif

/*! Frame buffer stride: Frame buffer stride should be set to a multiple of 32 or 128
    in accordance with the frame buffer burst transfer mode. */
/* FRAME BUFFER Parameter GRAPHICS_LAYER_0 */
#if ( VIDEO_INPUT_FORMAT == VIDEO_YCBCR422 || VIDEO_INPUT_FORMAT == VIDEO_RGB565 )
  #define FRAME_BUFFER_BYTE_PER_PIXEL (2u)
#else
  #define FRAME_BUFFER_BYTE_PER_PIXEL (4u)
#endif
#define FRAME_BUFFER_STRIDE           (((LCD_PIXEL_WIDTH * FRAME_BUFFER_BYTE_PER_PIXEL) + 31u) & ~31u)

static DisplayBase Display;
static DigitalOut  lcd_pwon(P7_15);
static DigitalOut  lcd_blon(P8_1);
static PwmOut      lcd_cntrst(P8_15);
static DigitalOut  led_blue(LED_BLUE);

#if defined(__ICCARM__)
/* 32 bytes aligned */
#pragma data_alignment=32
static uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * LCD_PIXEL_HEIGHT];
#pragma data_alignment=4
#else
/* 32 bytes aligned */
static uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * LCD_PIXEL_HEIGHT]__attribute((aligned(32)));
#endif
static bool graphics_init_end = false;

/****** LCD ******/
static void Init_LCD_Display(void) {
    DisplayBase::graphics_error_t error;
    DisplayBase::lcd_config_t lcd_config;
    PinName lvds_pin[8] = {
        /* data pin */
        P5_7, P5_6, P5_5, P5_4, P5_3, P5_2, P5_1, P5_0
    };

    lcd_pwon = 0;
    lcd_blon = 0;
    Thread::wait(100);
    lcd_pwon = 1;
    lcd_blon = 1;

    Display.Graphics_Lvds_Port_Init(lvds_pin, 8);

    /* Graphics initialization process */
    lcd_config = LcdCfgTbl_LCD_shield;
    error = Display.Graphics_init(&lcd_config);
    if (error != DisplayBase::GRAPHICS_OK) {
        printf("Line %d, error %d\n", __LINE__, error);
        mbed_die();
    }
    graphics_init_end = true;
}

static void Start_LCD_Display(uint8_t * p_buf) {
    DisplayBase::rect_t rect;

    rect.vs = 0;
    rect.vw = LCD_PIXEL_HEIGHT;
    rect.hs = 0;
    rect.hw = LCD_PIXEL_WIDTH;
    Display.Graphics_Read_Setting(
        DisplayBase::GRAPHICS_LAYER_0,
        (void *)p_buf,
        FRAME_BUFFER_STRIDE,
        GRAPHICS_FORMAT,
        WR_RD_WRSWA,
        &rect
    );
    Display.Graphics_Start(DisplayBase::GRAPHICS_LAYER_0);
}

/****** Video ******/
static void Init_Video(void) {
    DisplayBase::graphics_error_t error;

    /* Graphics initialization process */
    if (graphics_init_end == false) {
        /* When not initializing LCD, this processing is needed. */
        error = Display.Graphics_init(NULL);
        if (error != DisplayBase::GRAPHICS_OK) {
            printf("Line %d, error %d\n", __LINE__, error);
            mbed_die();
        }
        graphics_init_end = true;
    }

    error = Display.Graphics_Video_init( DisplayBase::INPUT_SEL_VDEC, NULL);
    if( error != DisplayBase::GRAPHICS_OK ) {
        printf("Line %d, error %d\n", __LINE__, error);
        mbed_die();
    }
}

static void Start_Video(DisplayBase::video_input_channel_t ch, uint8_t * p_frame_buffer,
 uint16_t pos_x, uint16_t pos_y, uint16_t width, uint16_t height) {
    DisplayBase::graphics_error_t error;
    uint8_t * p_buf;

    p_buf = p_frame_buffer + (FRAME_BUFFER_BYTE_PER_PIXEL * pos_x) + (FRAME_BUFFER_STRIDE * pos_y);

    /* Video capture setting (progressive form fixed) */
    error = Display.Video_Write_Setting(
                ch,
                COL_SYS,
                p_buf,
                FRAME_BUFFER_STRIDE,
                VIDEO_FORMAT,
                WR_RD_WRSWA,
                (height & ~7u),      /* A multiple of 8 */
                (width  & ~15u)      /* A multiple of 16 */
            );
    if (error != DisplayBase::GRAPHICS_OK) {
        printf("Line %d, error %d\n", __LINE__, error);
        mbed_die();
    }

    /* Video write process start */
    error = Display.Video_Start(ch);
    if (error != DisplayBase::GRAPHICS_OK) {
        printf("Line %d, error %d\n", __LINE__, error);
        mbed_die();
    }

    /* Video write process stop */
    error = Display.Video_Stop(ch);
    if (error != DisplayBase::GRAPHICS_OK) {
        printf("Line %d, error %d\n", __LINE__, error);
        mbed_die();
    }

    /* Video write process start */
    error = Display.Video_Start(ch);
    if (error != DisplayBase::GRAPHICS_OK) {
        printf("Line %d, error %d\n", __LINE__, error);
        mbed_die();
    }
}

/****** Cache control ******/
static void dcache_clean(void * p_buf, uint32_t size){
    uint32_t start_addr = (uint32_t)p_buf & 0xFFFFFFE0;
    uint32_t end_addr   = (uint32_t)p_buf + size;
    uint32_t addr;

    /* Data cache clean */
    for (addr = start_addr; addr < end_addr; addr += 0x20) {
        __v7_clean_dcache_mva((void *)addr);
    }
}

/****** main ******/
int main(void) {
    /* Initialization of LCD */
    Init_LCD_Display();    /* When using LCD, please call before than Init_Video(). */

    /* Initialization of Video */
    Init_Video();

    /* Initialization memory */
#if VIDEO_INPUT_FORMAT == VIDEO_YCBCR422
    for (int i = 0; i < sizeof(user_frame_buffer0); i += 2) {
        user_frame_buffer0[i + 0] = 0x10;
        user_frame_buffer0[i + 1] = 0x80;
    }
#else
    memset(user_frame_buffer0, 0, sizeof(user_frame_buffer0));
#endif
    dcache_clean(user_frame_buffer0, sizeof(user_frame_buffer0));

    /* Start of Video ch0 */
    Start_Video(
        DisplayBase::VIDEO_INPUT_CHANNEL_0,   /* Video input channe */
        user_frame_buffer0,                   /* Output buffer */
        0,                                    /* The x coordinate of the upper-left corner */
        0,                                    /* The y coordinate of the upper-left corner */
        (LCD_PIXEL_WIDTH / 2),                /* width  (A multiple of 16) */
        LCD_PIXEL_HEIGHT                      /* height (A multiple of 8) */
    );

    /* Start of Video ch1 */
    Start_Video(
        DisplayBase::VIDEO_INPUT_CHANNEL_1,   /* Video input channe */
        user_frame_buffer0,                   /* Output buffer */
        (LCD_PIXEL_WIDTH / 2),                /* The x coordinate of the upper-left corner */
        0,                                    /* The y coordinate of the upper-left corner */
        (LCD_PIXEL_WIDTH / 2),                /* width  (A multiple of 16) */
        LCD_PIXEL_HEIGHT                      /* height (A multiple of 8) */
    );

    /* Start of LCD */
    Start_LCD_Display(&user_frame_buffer0[0]);

    /* Backlight on */
    Thread::wait(200);
    lcd_cntrst.write(1.0);

    while (1) {
        led_blue = !led_blue;
        Thread::wait(1000);
    }
}