test
Dependencies: mbed GR-PEACH_video mbed-rtos LCD_shield_config
Diff: main.cpp
- Revision:
- 0:b2184c2d15dd
- Child:
- 1:54a3e69f6f09
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Thu Jun 30 11:05:41 2016 +0000 @@ -0,0 +1,549 @@ +#include "mbed.h" +#include "DisplayBace.h" +#include "rtos.h" + +#define VIDEO_CVBS (0) /* Analog Video Signal */ +#define VIDEO_CMOS_CAMERA (1) /* Digital Video Signal */ +#define VIDEO_YCBCR422 (0) +#define VIDEO_RGB888 (1) +#define VIDEO_RGB565 (2) + +/**** User Selection *********/ +/** Camera **/ +#define VIDEO_INPUT_METHOD (VIDEO_CMOS_CAMERA) /* Select VIDEO_CVBS or VIDEO_CMOS_CAMERA */ +#define VIDEO_INPUT_FORMAT (VIDEO_YCBCR422) /* Select VIDEO_YCBCR422 or VIDEO_RGB888 or VIDEO_RGB565 */ +#define USE_VIDEO_CH (0) /* Select 0 or 1 If selecting VIDEO_CMOS_CAMERA, should be 0.) */ +#define VIDEO_PAL (0) /* Select 0(NTSC) or 1(PAL) If selecting VIDEO_CVBS, this parameter is not referenced.) */ +/** LCD **/ +#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 **/ +/* video input */ +#if USE_VIDEO_CH == (0) + #define VIDEO_INPUT_CH (DisplayBase::VIDEO_INPUT_CHANNEL_0) + #define VIDEO_INT_TYPE (DisplayBase::INT_TYPE_S0_VFIELD) +#else + #define VIDEO_INPUT_CH (DisplayBase::VIDEO_INPUT_CHANNEL_1) + #define VIDEO_INT_TYPE (DisplayBase::INT_TYPE_S1_VFIELD) +#endif + +/* 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 + +/* The size of the video input is adjusted to the LCD size. */ +#define VIDEO_PIXEL_HW LCD_PIXEL_WIDTH +#define VIDEO_PIXEL_VW LCD_PIXEL_HEIGHT + +/*! 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 */ +#define FRAME_BUFFER_NUM (3u) +#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) + +/* TOUCH BUFFER Parameter GRAPHICS_LAYER_1 */ +#define TOUCH_BUFFER_BYTE_PER_PIXEL (2u) +#define TOUCH_BUFFER_STRIDE (((LCD_PIXEL_WIDTH * TOUCH_BUFFER_BYTE_PER_PIXEL) + 31u) & ~31u) + +/* Touch panel parameter */ +#define TOUCH_NUM (2u) +#define DROW_POINT (5) + +static DisplayBase Display; +static DigitalOut lcd_pwon(P7_15); +static DigitalOut lcd_blon(P8_1); +static PwmOut lcd_cntrst(P8_15); +static Serial pc(USBTX, USBRX); +static Semaphore sem_touch_int(0); +static TouckKey_LCD_shield touch(P4_0, P2_13, I2C_SDA, I2C_SCL); +static Thread * p_VideoLcdTask = NULL; +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]; +static uint8_t user_frame_buffer1[FRAME_BUFFER_STRIDE * LCD_PIXEL_HEIGHT]; +static uint8_t user_frame_buffer2[FRAME_BUFFER_STRIDE * LCD_PIXEL_HEIGHT]; +static uint8_t user_frame_buffer_touch[TOUCH_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))); +static uint8_t user_frame_buffer1[FRAME_BUFFER_STRIDE * LCD_PIXEL_HEIGHT]__attribute((aligned(32))); +static uint8_t user_frame_buffer2[FRAME_BUFFER_STRIDE * LCD_PIXEL_HEIGHT]__attribute((aligned(32))); +static uint8_t user_frame_buffer_touch[TOUCH_BUFFER_STRIDE * LCD_PIXEL_HEIGHT]__attribute((aligned(32))); +#endif +static volatile int32_t vfield_count = 0; +static uint8_t * FrameBufferTbl[FRAME_BUFFER_NUM] = {user_frame_buffer0, user_frame_buffer1, user_frame_buffer2}; +static int write_buff_num = 0; +static int read_buff_num = 0; +static bool graphics_init_end = false; + +/****** 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); + } +} + +/****** LCD ******/ +#if(0) /* When needing LCD Vsync interrupt, please make it effective. */ +static void IntCallbackFunc_LoVsync(DisplayBase::int_type_t int_type) { + /* Interrupt callback function for Vsync interruption */ +} +#endif + +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; + +#if(0) /* When needing LCD Vsync interrupt, please make it effective. */ + /* Interrupt callback function setting (Vsync signal output from scaler 0) */ + error = Display.Graphics_Irq_Handler_Set(DisplayBase::INT_TYPE_S0_LO_VSYNC, 0, IntCallbackFunc_LoVsync); + if (error != DisplayBase::GRAPHICS_OK) { + printf("Line %d, error %d\n", __LINE__, error); + mbed_die(); + } +#endif +} + +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 ******/ +#if(0) /* When needing video Vsync interrupt, please make it effective. */ +static void IntCallbackFunc_ViVsync(DisplayBase::int_type_t int_type) { + /* Interrupt callback function for Vsync interruption */ +} +#endif + +static void IntCallbackFunc_Vfield(DisplayBase::int_type_t int_type) { + /* Interrupt callback function */ + if (vfield_count == 0) { + vfield_count = 1; + } else { + vfield_count = 0; + if (p_VideoLcdTask != NULL) { + p_VideoLcdTask->signal_set(1); + } + } +} + +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; + } + +#if VIDEO_INPUT_METHOD == VIDEO_CVBS + 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(); + } +#elif VIDEO_INPUT_METHOD == VIDEO_CMOS_CAMERA + DisplayBase::video_ext_in_config_t ext_in_config; + PinName cmos_camera_pin[11] = { + /* data pin */ + P2_7, P2_6, P2_5, P2_4, P2_3, P2_2, P2_1, P2_0, + /* control pin */ + P10_0, /* DV0_CLK */ + P1_0, /* DV0_Vsync */ + P1_1 /* DV0_Hsync */ + }; + + /* MT9V111 camera input config */ + ext_in_config.inp_format = DisplayBase::VIDEO_EXTIN_FORMAT_BT601; /* BT601 8bit YCbCr format */ + ext_in_config.inp_pxd_edge = DisplayBase::EDGE_RISING; /* Clock edge select for capturing data */ + ext_in_config.inp_vs_edge = DisplayBase::EDGE_RISING; /* Clock edge select for capturing Vsync signals */ + ext_in_config.inp_hs_edge = DisplayBase::EDGE_RISING; /* Clock edge select for capturing Hsync signals */ + ext_in_config.inp_endian_on = DisplayBase::OFF; /* External input bit endian change on/off */ + ext_in_config.inp_swap_on = DisplayBase::OFF; /* External input B/R signal swap on/off */ + ext_in_config.inp_vs_inv = DisplayBase::SIG_POL_NOT_INVERTED; /* External input DV_VSYNC inversion control */ + ext_in_config.inp_hs_inv = DisplayBase::SIG_POL_INVERTED; /* External input DV_HSYNC inversion control */ + ext_in_config.inp_f525_625 = DisplayBase::EXTIN_LINE_525; /* Number of lines for BT.656 external input */ + ext_in_config.inp_h_pos = DisplayBase::EXTIN_H_POS_CRYCBY; /* Y/Cb/Y/Cr data string start timing to Hsync reference */ + ext_in_config.cap_vs_pos = 6; /* Capture start position from Vsync */ + ext_in_config.cap_hs_pos = 150; /* Capture start position form Hsync */ +#if (LCD_TYPE == 0) + /* The same screen ratio as the screen ratio of the LCD. */ + ext_in_config.cap_width = 640; /* Capture width */ + ext_in_config.cap_height = 363; /* Capture height Max 468[line] + Due to CMOS(MT9V111) output signal timing and VDC5 specification */ +#else + ext_in_config.cap_width = 640; /* Capture width */ + ext_in_config.cap_height = 468u; /* Capture height Max 468[line] + Due to CMOS(MT9V111) output signal timing and VDC5 specification */ +#endif + error = Display.Graphics_Video_init( DisplayBase::INPUT_SEL_EXT, &ext_in_config); + if( error != DisplayBase::GRAPHICS_OK ) { + printf("Line %d, error %d\n", __LINE__, error); + mbed_die(); + } + + /* MT9V111 camera input port setting */ + error = Display.Graphics_Dvinput_Port_Init(cmos_camera_pin, 11); + if( error != DisplayBase::GRAPHICS_OK ) { + printf("Line %d, error %d\n", __LINE__, error); + mbed_die(); + } +#endif + +#if(0) /* When needing video Vsync interrupt, please make it effective. */ + /* Interrupt callback function setting (Vsync signal input to scaler 0) */ + error = Display.Graphics_Irq_Handler_Set(DisplayBase::INT_TYPE_S0_VI_VSYNC, 0, IntCallbackFunc_ViVsync); + if (error != DisplayBase::GRAPHICS_OK) { + printf("Line %d, error %d\n", __LINE__, error); + mbed_die(); + } +#endif + + /* Interrupt callback function setting (Field end signal for recording function in scaler 0) */ + error = Display.Graphics_Irq_Handler_Set(VIDEO_INT_TYPE, 0, IntCallbackFunc_Vfield); + if (error != DisplayBase::GRAPHICS_OK) { + printf("Line %d, error %d\n", __LINE__, error); + mbed_die(); + } +} + +static void Start_Video(uint8_t * p_buf) { + DisplayBase::graphics_error_t error; + + /* Video capture setting (progressive form fixed) */ + error = Display.Video_Write_Setting( + VIDEO_INPUT_CH, + COL_SYS, + p_buf, + FRAME_BUFFER_STRIDE, + VIDEO_FORMAT, + WR_RD_WRSWA, + VIDEO_PIXEL_VW, + VIDEO_PIXEL_HW + ); + if (error != DisplayBase::GRAPHICS_OK) { + printf("Line %d, error %d\n", __LINE__, error); + mbed_die(); + } + + /* Video write process start */ + error = Display.Video_Start(VIDEO_INPUT_CH); + if (error != DisplayBase::GRAPHICS_OK) { + printf("Line %d, error %d\n", __LINE__, error); + mbed_die(); + } + + /* Video write process stop */ + error = Display.Video_Stop(VIDEO_INPUT_CH); + if (error != DisplayBase::GRAPHICS_OK) { + printf("Line %d, error %d\n", __LINE__, error); + mbed_die(); + } + + /* Video write process start */ + error = Display.Video_Start(VIDEO_INPUT_CH); + if (error != DisplayBase::GRAPHICS_OK) { + printf("Line %d, error %d\n", __LINE__, error); + mbed_die(); + } +} + +/****** Video input is output to LCD ******/ +static void video_lcd_task(void const *) { + DisplayBase::graphics_error_t error; + int wk_num; + int i; + + /* Initialization memory */ + for (i = 0; i < FRAME_BUFFER_NUM; i++) { + memset(FrameBufferTbl[i], 0, (FRAME_BUFFER_STRIDE * LCD_PIXEL_HEIGHT)); + dcache_clean(FrameBufferTbl[i], (FRAME_BUFFER_STRIDE * LCD_PIXEL_HEIGHT)); + } + + /* Start of Video */ + Start_Video(FrameBufferTbl[write_buff_num]); + + /* Wait for first video drawing */ + Thread::signal_wait(1); + write_buff_num++; + if (write_buff_num >= FRAME_BUFFER_NUM) { + write_buff_num = 0; + } + error = Display.Video_Write_Change(VIDEO_INPUT_CH, FrameBufferTbl[write_buff_num], FRAME_BUFFER_STRIDE); + if (error != DisplayBase::GRAPHICS_OK) { + printf("Line %d, error %d\n", __LINE__, error); + mbed_die(); + } + + /* Start of LCD */ + Start_LCD_Display(FrameBufferTbl[read_buff_num]); + + /* Backlight on */ + Thread::wait(200); + lcd_cntrst.write(1.0); + + while (1) { + Thread::signal_wait(1); + wk_num = write_buff_num + 1; + if (wk_num >= FRAME_BUFFER_NUM) { + wk_num = 0; + } + /* If the next buffer is empty, it's changed. */ + if (wk_num != read_buff_num) { + read_buff_num = write_buff_num; + write_buff_num = wk_num; + /* Change video buffer */ + error = Display.Video_Write_Change(VIDEO_INPUT_CH, FrameBufferTbl[write_buff_num], FRAME_BUFFER_STRIDE); + if (error != DisplayBase::GRAPHICS_OK) { + printf("Line %d, error %d\n", __LINE__, error); + mbed_die(); + } + /* Change LCD buffer */ + Display.Graphics_Read_Change(DisplayBase::GRAPHICS_LAYER_0, (void *)FrameBufferTbl[read_buff_num]); + } + } +} + +/****** Touch panel ******/ +static void drow_touch_pos(uint8_t * p_buf, int id, int x, int y) { + int idx_base; + int wk_idx; + int i; + int j; + uint8_t coller_pix[TOUCH_BUFFER_BYTE_PER_PIXEL]; /* ARGB4444 */ + + /* A coordinate in the upper left is calculated from a central coordinate. */ + if ((x - (DROW_POINT / 2)) >= 0) { + x -= (DROW_POINT / 2); + } + if (x > (LCD_PIXEL_WIDTH - DROW_POINT)) { + x = (LCD_PIXEL_WIDTH - DROW_POINT); + } + if ((y - (DROW_POINT / 2)) >= 0) { + y -= (DROW_POINT / 2); + } + if (y > (LCD_PIXEL_HEIGHT - DROW_POINT)) { + y = (LCD_PIXEL_HEIGHT - DROW_POINT); + } + idx_base = (x + (LCD_PIXEL_WIDTH * y)) * TOUCH_BUFFER_BYTE_PER_PIXEL; + + /* Select color */ + if (id == 0) { + /* Blue */ + coller_pix[0] = 0x0F; /* 4:Green 4:Blue */ + coller_pix[1] = 0xF0; /* 4:Alpha 4:Red */ + } else { + /* Pink */ + coller_pix[0] = 0x07; /* 4:Green 4:Blue */ + coller_pix[1] = 0xFF; /* 4:Alpha 4:Red */ + } + + /* Drawing */ + for (i = 0; i < DROW_POINT; i++) { + wk_idx = idx_base + (LCD_PIXEL_WIDTH * TOUCH_BUFFER_BYTE_PER_PIXEL * i); + for (j = 0; j < DROW_POINT; j++) { + p_buf[wk_idx++] = coller_pix[0]; + p_buf[wk_idx++] = coller_pix[1]; + } + } +} + +static void drow_touch_keyonoff(uint8_t * p_buf, int id, bool onoff) { + int idx_base; + int wk_idx; + int i; + int j; + uint8_t coller_pix[TOUCH_BUFFER_BYTE_PER_PIXEL]; /* ARGB4444 */ + + /* Display position */ + if (id == 0) { + idx_base = 0; + } else { + idx_base = DROW_POINT * TOUCH_BUFFER_BYTE_PER_PIXEL; + } + + /* Select color */ + if (onoff == false) { + /* Transparency */ + coller_pix[0] = 0x00; /* 4:Green 4:Blue */ + coller_pix[1] = 0x00; /* 4:Alpha 4:Red */ + } else { + /* White */ + coller_pix[0] = 0xff; /* 4:Green 4:Blue */ + coller_pix[1] = 0xff; /* 4:Alpha 4:Red */ + } + + /* Drawing */ + for (i = 0; i < DROW_POINT; i++) { + wk_idx = idx_base + (LCD_PIXEL_WIDTH * TOUCH_BUFFER_BYTE_PER_PIXEL * i); + for (j = 0; j < DROW_POINT; j++) { + p_buf[wk_idx++] = coller_pix[0]; + p_buf[wk_idx++] = coller_pix[1]; + } + } +} + +static void touch_int_callback(void) { + sem_touch_int.release(); +} + +static void touch_task(void const *) { + DisplayBase::rect_t rect; + TouchKey::touch_pos_t touch_pos[TOUCH_NUM]; + int touch_num = 0; + int touch_num_last = 0; + int i; + + /* The layer by which the touch panel location is drawn */ + memset(user_frame_buffer_touch, 0, sizeof(user_frame_buffer_touch)); + dcache_clean(user_frame_buffer_touch, sizeof(user_frame_buffer_touch)); + rect.vs = 0; + rect.vw = LCD_PIXEL_HEIGHT; + rect.hs = 0; + rect.hw = LCD_PIXEL_WIDTH; + Display.Graphics_Read_Setting( + DisplayBase::GRAPHICS_LAYER_1, + (void *)user_frame_buffer_touch, + TOUCH_BUFFER_STRIDE, + DisplayBase::GRAPHICS_FORMAT_ARGB4444, + DisplayBase::WR_RD_WRSWA_32_16BIT, + &rect + ); + Display.Graphics_Start(DisplayBase::GRAPHICS_LAYER_1); + + /* Callback setting */ + touch.SetCallback(&touch_int_callback); + + /* Reset touch IC */ + touch.Reset(); + + while (1) { + /* Wait touch event */ + sem_touch_int.wait(); + + /* Get touch coordinates */ + touch_num = touch.GetCoordinates(TOUCH_NUM, touch_pos); + + /* When it's a new touch, touch frame buffer is initialized */ + if ((touch_num != 0) && (touch_num_last == 0)) { + memset(user_frame_buffer_touch, 0, sizeof(user_frame_buffer_touch)); + } + touch_num_last = touch_num; + + /* Drawing of a touch coordinate */ + for (i = 0; i < TOUCH_NUM; i ++) { + printf("{valid=%d,x=%d,y=%d} ", touch_pos[i].valid, touch_pos[i].x, touch_pos[i].y); + drow_touch_keyonoff(user_frame_buffer_touch, i, touch_pos[i].valid); + if (touch_pos[i].valid) { + drow_touch_pos(user_frame_buffer_touch, i, touch_pos[i].x, touch_pos[i].y); + } + } + printf("\n"); + + /* Data cache clean */ + dcache_clean(user_frame_buffer_touch, sizeof(user_frame_buffer_touch)); + } +} + +/****** main ******/ +int main(void) { + /* Change the baud rate of the printf() */ + pc.baud(921600); + + /* Initialization of LCD */ + Init_LCD_Display(); /* When using LCD, please call before than Init_Video(). */ + + /* Initialization of Video */ + Init_Video(); + + /* Start Video and Lcd processing */ + p_VideoLcdTask = new Thread(video_lcd_task, NULL, osPriorityAboveNormal, 1024 * 4); + + /* Start touch panel processing */ + Thread touchTask(touch_task, NULL, osPriorityNormal, 1024 * 4); + + while (1) { + led_blue = !led_blue; + Thread::wait(1000); + } +}