GR-PEACH Digital Signage sample for DISPLAY SHIELD.

Dependencies:   GR-PEACH_video GraphicsFramework R_BSP SDFileSystem_tmp mbed-rtos mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002 Permission is hereby granted, free of charge, to any person obtaining a copy
00003 of this software and associated documentation files (the "Software"), to deal
00004 in the Software without restriction, including without limitation the rights
00005 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00006 copies of the Software, and to permit persons to whom the Software is
00007 furnished to do so, subject to the following conditions:
00008  
00009 The above copyright notice and this permission notice shall be included in
00010 all copies or substantial portions of the Software.
00011  
00012 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00013 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00014 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00015 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00016 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00017 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00018 THE SOFTWARE.
00019 */
00020 
00021 #include "mbed.h"
00022 #include "DisplayBace.h"
00023 #include "RGA.h"
00024 #include "rtos.h"
00025 #include "SDFileSystem.h"
00026 
00027 #define SVGA                                (0u)  /*  800x600@60  37.9kHz/60Hz */
00028 #define XGA                                 (1u)  /* 1024x768@60  48.4kHz/60Hz */
00029 #define HD_720p                             (2u)  /* 1280x720@60  45.0kHz/60Hz */
00030 
00031 /**** User Selection *********/
00032 #define WAIT_TIME                           (10000) /* wait time (ms) */
00033 #define DISSOLVE_STEP_NUM                   (16)    /* minimum 1 */
00034 #define SCROLL_STEP_NUM                     (8)     /* minimum 1 */
00035 #define SCROLL_DIRECTION                    (-1)    /* Select 1(left to right) or -1(right to left) */
00036 #define LCD_SIZE                            HD_720p /* Select SVGA, XGA, or HD_720p */
00037 /*****************************/
00038 
00039 #define FILE_NAME_LEN                       (64)
00040 #define TEXT_SIZE                           (64 + 1) //null-terminated
00041 #define FLD_PATH                            "/sd/"
00042 #define MAX_JPEG_SIZE                       (1024 * 450)
00043 
00044 /* LCD Parameter */
00045 #define LCD_INPUT_CLOCK                     (66.67)
00046 #if ( LCD_SIZE == SVGA )
00047 #define LCD_OUTPUT_CLOCK                    (40.0003)
00048 #define LCD_PIXEL_WIDTH                     (800u)
00049 #define LCD_PIXEL_HEIGHT                    (600u)
00050 #define LCD_H_BACK_PORCH                    (88u)
00051 #define LCD_H_FRONT_PORCH                   (40u)
00052 #define LCD_H_SYNC_WIDTH                    (128u)
00053 #define LCD_V_BACK_PORCH                    (23u)
00054 #define LCD_V_FRONT_PORCH                   (1u)
00055 #define LCD_V_SYNC_WIDTH                    (4u)
00056 #elif ( LCD_SIZE == XGA )
00057 #define LCD_OUTPUT_CLOCK                    (65.0002)
00058 #define LCD_PIXEL_WIDTH                     (1024u)
00059 #define LCD_PIXEL_HEIGHT                    (768u)
00060 #define LCD_H_BACK_PORCH                    (160u)
00061 #define LCD_H_FRONT_PORCH                   (24u)
00062 #define LCD_H_SYNC_WIDTH                    (136u)
00063 #define LCD_V_BACK_PORCH                    (29u)
00064 #define LCD_V_FRONT_PORCH                   (3u)
00065 #define LCD_V_SYNC_WIDTH                    (6u)
00066 #elif ( LCD_SIZE == HD_720p )
00067 #define LCD_OUTPUT_CLOCK                    (74.1800)
00068 #define LCD_PIXEL_WIDTH                     (1280u)
00069 #define LCD_PIXEL_HEIGHT                    (720u)
00070 #define LCD_H_BACK_PORCH                    (220u)
00071 #define LCD_H_FRONT_PORCH                   (70u)
00072 #define LCD_H_SYNC_WIDTH                    (80u)
00073 #define LCD_V_BACK_PORCH                    (20u)
00074 #define LCD_V_FRONT_PORCH                   (5u)
00075 #define LCD_V_SYNC_WIDTH                    (5u)
00076 #endif
00077 
00078 /* FRAME BUFFER Parameter */
00079 #define FRAME_BUFFER_BYTE_PER_PIXEL         (2)
00080 #define FRAME_BUFFER_STRIDE                 (((LCD_PIXEL_WIDTH * FRAME_BUFFER_BYTE_PER_PIXEL) + 31u) & ~31u)
00081 
00082 DigitalIn   button(USER_BUTTON0);
00083 I2C         i2c(I2C_SDA, I2C_SCL);
00084 DisplayBase Display;
00085 Canvas2D_ContextClass canvas2d;
00086 
00087 #if defined(__ICCARM__)
00088 #pragma data_alignment=32
00089 static uint8_t user_frame_buffer[FRAME_BUFFER_STRIDE * LCD_PIXEL_HEIGHT];
00090 static uint8_t user_frame_buffer2[FRAME_BUFFER_STRIDE * LCD_PIXEL_HEIGHT];
00091 #pragma data_alignment=8
00092 static uint8_t JpegBuffer[MAX_JPEG_SIZE]@ ".mirrorram";  //8 bytes aligned!;
00093 #pragma data_alignment=4
00094 #else
00095 static uint8_t user_frame_buffer[FRAME_BUFFER_STRIDE * LCD_PIXEL_HEIGHT]__attribute((aligned(32)));  /* 32 bytes aligned */
00096 static uint8_t user_frame_buffer2[FRAME_BUFFER_STRIDE * LCD_PIXEL_HEIGHT]__attribute((aligned(32))); /* 32 bytes aligned */
00097 static uint8_t JpegBuffer[MAX_JPEG_SIZE]__attribute((section("NC_BSS"),aligned(8)));  //8 bytes aligned!;
00098 #endif
00099 static frame_buffer_t frame_buffer_info;
00100 static volatile int32_t vsync_count = 0;
00101 
00102 static void IntCallbackFunc_Vsync(DisplayBase::int_type_t int_type) {
00103     /* Interrupt callback function for Vsync interruption */
00104     if (vsync_count > 0) {
00105         vsync_count--;
00106     }
00107 }
00108 
00109 static void Wait_Vsync(const int32_t wait_count) {
00110     /* Wait for the specified number of times Vsync occurs */
00111     vsync_count = wait_count;
00112     while (vsync_count > 0) {
00113         /* Do nothing */
00114     }
00115 }
00116 
00117 static void Init_LCD_Display(uint8_t* disp_buf) {
00118     /* Create DisplayBase object */
00119     DisplayBase::graphics_error_t error;
00120     DisplayBase::rect_t rect;
00121     DisplayBase::lcd_config_t lcd_config;
00122     PinName lcd_pin[28] = {
00123         /* data pin */
00124         P11_15, P11_14, P11_13, P11_12, P5_7, P5_6, P5_5, P5_4, P5_3, P5_2, P5_1, P5_0,
00125         P4_7, P4_6, P4_5, P4_4, P10_12, P10_13, P10_14, P10_15, P3_15, P3_14, P3_13,
00126         P3_12, P3_11, P3_10, P3_9, P3_8
00127     };
00128 
00129     Thread::wait(100);
00130 
00131     lcd_config.lcd_type             = DisplayBase::LCD_TYPE_PARALLEL_RGB;
00132     lcd_config.intputClock          = LCD_INPUT_CLOCK;
00133     lcd_config.outputClock          = LCD_OUTPUT_CLOCK;
00134     lcd_config.lcd_outformat        = DisplayBase::LCD_OUTFORMAT_RGB888;
00135     lcd_config.lcd_edge             = DisplayBase::EDGE_RISING;
00136     lcd_config.h_toatal_period      = (LCD_PIXEL_WIDTH  + LCD_H_FRONT_PORCH + LCD_H_BACK_PORCH + LCD_H_SYNC_WIDTH);
00137     lcd_config.v_toatal_period      = (LCD_PIXEL_HEIGHT + LCD_V_FRONT_PORCH + LCD_V_BACK_PORCH + LCD_V_SYNC_WIDTH);
00138 
00139     lcd_config.h_disp_widht         = LCD_PIXEL_WIDTH;
00140     lcd_config.v_disp_widht         = LCD_PIXEL_HEIGHT;
00141     lcd_config.h_back_porch         = LCD_H_BACK_PORCH;
00142     lcd_config.v_back_porch         = LCD_V_BACK_PORCH;
00143 
00144     lcd_config.h_sync_port          = DisplayBase::LCD_TCON_PIN_1;
00145     lcd_config.h_sync_port_polarity = DisplayBase::SIG_POL_NOT_INVERTED;
00146     lcd_config.h_sync_width         = LCD_H_SYNC_WIDTH;
00147 
00148     lcd_config.v_sync_port          = DisplayBase::LCD_TCON_PIN_2;
00149     lcd_config.v_sync_port_polarity = DisplayBase::SIG_POL_NOT_INVERTED;
00150     lcd_config.v_sync_width         = LCD_V_SYNC_WIDTH;
00151 
00152     lcd_config.de_port              = DisplayBase::LCD_TCON_PIN_0;
00153     lcd_config.de_port_polarity     = DisplayBase::SIG_POL_NOT_INVERTED;
00154 
00155     /* Graphics initialization process */
00156     error = Display.Graphics_init(&lcd_config);
00157     if (error != DisplayBase::GRAPHICS_OK) {
00158         printf("Line %d, error %d\n", __LINE__, error);
00159         while (1);
00160     }
00161 
00162     /* Interrupt callback function setting (Vsync signal output from scaler 0) */
00163     error = Display.Graphics_Irq_Handler_Set(DisplayBase::INT_TYPE_S0_LO_VSYNC, 0, IntCallbackFunc_Vsync);
00164     if (error != DisplayBase::GRAPHICS_OK) {
00165         printf("Line %d, error %d\n", __LINE__, error);
00166         while (1);
00167     }
00168 
00169     Display.Graphics_Lcd_Port_Init(lcd_pin, 28);
00170     rect.vs = 0;
00171     rect.vw = LCD_PIXEL_HEIGHT;
00172     rect.hs = 0;
00173     rect.hw = LCD_PIXEL_WIDTH;
00174 
00175     Display.Graphics_Read_Setting(
00176         DisplayBase::GRAPHICS_LAYER_0,
00177         (void *)disp_buf,
00178         FRAME_BUFFER_STRIDE,
00179         DisplayBase::GRAPHICS_FORMAT_RGB565,
00180         DisplayBase::WR_RD_WRSWA_32_16BIT,
00181         &rect
00182     );
00183 }
00184 
00185 static void Start_LCD_Display(void) {
00186     Display.Graphics_Start(DisplayBase::GRAPHICS_LAYER_0);
00187 }
00188 
00189 static void Update_LCD_Display(frame_buffer_t * frmbuf_info) {
00190     Display.Graphics_Read_Change(DisplayBase::GRAPHICS_LAYER_0,
00191      (void *)frmbuf_info->buffer_address[frmbuf_info->draw_buffer_index]);
00192     Wait_Vsync(1);
00193 }
00194 
00195 static void Swap_FrameBuffer(frame_buffer_t * frmbuf_info) {
00196     if (frmbuf_info->draw_buffer_index == 1) {
00197         frmbuf_info->draw_buffer_index = 0;
00198     } else {
00199         frmbuf_info->draw_buffer_index = 1;
00200     }
00201 }
00202 
00203 static void draw_image(frame_buffer_t* frmbuf_info, const graphics_image_t* image_new) {
00204     Swap_FrameBuffer(frmbuf_info);
00205     /* Clear */
00206     canvas2d.clearRect(0, 0, frmbuf_info->width, frmbuf_info->height);
00207     /* Draw a image */
00208     canvas2d.globalAlpha = 1.0f;
00209     canvas2d.drawImage((const graphics_image_t*)image_new, 0, 0, frmbuf_info->width, frmbuf_info->height);
00210     R_OSPL_CLEAR_ERROR();
00211     /* Complete drawing */
00212     R_GRAPHICS_Finish(canvas2d.c_LanguageContext);
00213     Update_LCD_Display(frmbuf_info);
00214 }
00215 
00216 static void draw_image_scroll(frame_buffer_t* frmbuf_info, const graphics_image_t* image_last,
00217                               const graphics_image_t* image_new, float32_t scroll) {
00218     Swap_FrameBuffer(frmbuf_info);
00219     /* Clear */
00220     canvas2d.clearRect(0, 0, frmbuf_info->width, frmbuf_info->height);
00221     /* Draw a image */
00222     canvas2d.globalAlpha = 1.0f;
00223     canvas2d.drawImage((const graphics_image_t*)image_last,
00224                        (int_t)(frmbuf_info->width * scroll) * SCROLL_DIRECTION, 0,
00225                        frmbuf_info->width, frmbuf_info->height);
00226     R_OSPL_CLEAR_ERROR();
00227     canvas2d.globalAlpha = 1.0f;
00228     canvas2d.drawImage((const graphics_image_t*)image_new,
00229                        ((int_t)(frmbuf_info->width * scroll) - frmbuf_info->width) * SCROLL_DIRECTION, 0,
00230                        frmbuf_info->width, frmbuf_info->height);
00231     R_OSPL_CLEAR_ERROR();
00232     /* Complete drawing */
00233     R_GRAPHICS_Finish(canvas2d.c_LanguageContext);
00234     Update_LCD_Display(frmbuf_info);
00235 }
00236 
00237 static void draw_image_dissolve(frame_buffer_t* frmbuf_info, const graphics_image_t* image_last,
00238                                 const graphics_image_t* image_new, float32_t alpha) {
00239     Swap_FrameBuffer(frmbuf_info);
00240     /* Clear */
00241     canvas2d.clearRect(0, 0, frmbuf_info->width, frmbuf_info->height);
00242     /* Draw a image */
00243     canvas2d.globalAlpha = 1.0f - alpha;
00244     canvas2d.drawImage((const graphics_image_t*)image_last, 0, 0, frmbuf_info->width, frmbuf_info->height);
00245     R_OSPL_CLEAR_ERROR();
00246     canvas2d.globalAlpha = alpha;
00247     canvas2d.drawImage((const graphics_image_t*)image_new, 0, 0, frmbuf_info->width, frmbuf_info->height);
00248     R_OSPL_CLEAR_ERROR();
00249     /* Complete drawing */
00250     R_GRAPHICS_Finish(canvas2d.c_LanguageContext);
00251     Update_LCD_Display(frmbuf_info);
00252 }
00253 
00254 int main(void) {
00255     errnum_t err;
00256     Canvas2D_ContextConfigClass config;
00257 
00258     memset(user_frame_buffer, 0, sizeof(user_frame_buffer));
00259     memset(user_frame_buffer2, 0, sizeof(user_frame_buffer2));
00260     frame_buffer_info.buffer_address[0] = user_frame_buffer;
00261     frame_buffer_info.buffer_address[1] = user_frame_buffer2;
00262     frame_buffer_info.buffer_count      = 2;
00263     frame_buffer_info.show_buffer_index = 0;
00264     frame_buffer_info.draw_buffer_index = 0;
00265     frame_buffer_info.width             = LCD_PIXEL_WIDTH;
00266     frame_buffer_info.byte_per_pixel    = FRAME_BUFFER_BYTE_PER_PIXEL;
00267     frame_buffer_info.stride            = LCD_PIXEL_WIDTH * FRAME_BUFFER_BYTE_PER_PIXEL;
00268     frame_buffer_info.height            = LCD_PIXEL_HEIGHT;
00269     frame_buffer_info.pixel_format      = PIXEL_FORMAT_RGB565;
00270     Init_LCD_Display(frame_buffer_info.buffer_address[0]);
00271 
00272     config.frame_buffer = &frame_buffer_info;
00273     canvas2d = R_RGA_New_Canvas2D_ContextClass(config);
00274     err = R_OSPL_GetErrNum();
00275     if (err != 0) {
00276         printf("Line %d, error %d\n", __LINE__, err);
00277         while (1);
00278     }
00279     Start_LCD_Display();
00280 
00281     Thread::wait(100);  // wait sd mount
00282 
00283     SDFileSystem sd(P8_5, P8_6, P8_3, P8_4, "sd");
00284     FILE * fp = NULL;
00285     DIR  * d = NULL;
00286     char file_path[sizeof(FLD_PATH) + FILE_NAME_LEN];
00287     int jpeg_toggle = 0;
00288     bool first_view = true;
00289     size_t ret;
00290     Timer  t;
00291     uint8_t * p_JpegBuffer[2];
00292 
00293     p_JpegBuffer[0] = JpegBuffer;
00294     p_JpegBuffer[1] = new uint8_t[MAX_JPEG_SIZE];
00295 
00296     while (1) {
00297         // file search
00298         if (d == NULL) {
00299             d = opendir(FLD_PATH);
00300         }
00301         struct dirent * p;
00302         while ((p = readdir(d)) != NULL) {
00303             size_t len = strlen(p->d_name);
00304             if ((len > 4) && (len < FILE_NAME_LEN)
00305                 && (strncasecmp(&p->d_name[len - 4], ".jpg", 4) == 0)) {
00306                 strcpy(file_path, FLD_PATH);
00307                 strcat(file_path, p->d_name);
00308                 fp = fopen(file_path, "r");
00309                 ret = fread(p_JpegBuffer[jpeg_toggle], sizeof(char), MAX_JPEG_SIZE, fp);
00310                 fclose(fp);
00311                 if (ret < MAX_JPEG_SIZE) {
00312                     if (first_view != false) {
00313                         t.reset();
00314                         t.start();
00315                         // Effect NONE
00316                         first_view = false;
00317                         draw_image(&frame_buffer_info, (const graphics_image_t*)p_JpegBuffer[jpeg_toggle]);
00318                     } else {
00319                         bool key_press = false;
00320                         t.stop();
00321                         // Wait timeout or key press
00322                         for (int i = t.read_ms(); i < WAIT_TIME; i += 100) {
00323                             if (button == 0) {
00324                                 key_press = true;
00325                                 break;
00326                             }
00327                             Thread::wait(100);
00328                         }
00329                         t.reset();
00330                         t.start();
00331                         if (key_press == false) {
00332                             // Effect DISSOLVE
00333                             for (int i = 1; i <= DISSOLVE_STEP_NUM; i++) {
00334                                 draw_image_dissolve(&frame_buffer_info,
00335                                                     (const graphics_image_t*)p_JpegBuffer[!jpeg_toggle],
00336                                                     (const graphics_image_t*)p_JpegBuffer[jpeg_toggle],
00337                                                     (float32_t)i / (float32_t)DISSOLVE_STEP_NUM);
00338                             }
00339                         } else {
00340                             // Effect SCROLL
00341                             for (int i = 1; i <= SCROLL_STEP_NUM; i++) {
00342                                 draw_image_scroll(&frame_buffer_info,
00343                                                   (const graphics_image_t*)p_JpegBuffer[!jpeg_toggle],
00344                                                   (const graphics_image_t*)p_JpegBuffer[jpeg_toggle],
00345                                                   (float32_t)i / (float32_t)SCROLL_STEP_NUM);
00346                             }
00347                         }
00348                     }
00349                     jpeg_toggle = !jpeg_toggle;
00350                 }
00351                 break;
00352             }
00353         }
00354         if (p == NULL) {
00355             closedir(d);
00356             d = NULL;
00357         }
00358     }
00359 }