Osamu Nakamura / GR-PEACH_mbed-os-client-ZXingSample
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers zxing_main.cpp Source File

zxing_main.cpp

00001 
00002 #include "mbed.h"
00003 #include "rtos.h"
00004 #include "DisplayBace.h"
00005 #include "ImageReaderSource.h"
00006 
00007 #define VIDEO_CVBS             (0)                 /* Analog  Video Signal */
00008 #define VIDEO_CMOS_CAMERA      (1)                 /* Digital Video Signal */
00009 
00010 /**** User Selection *********/
00011 /** Camera setting **/
00012 #define VIDEO_INPUT_METHOD     (VIDEO_CMOS_CAMERA) /* Select  VIDEO_CVBS or VIDEO_CMOS_CAMERA                       */
00013 #define USE_VIDEO_CH           (0)                 /* Select  0 or 1            If selecting VIDEO_CMOS_CAMERA, should be 0.)               */
00014 #define VIDEO_PAL              (0)                 /* Select  0(NTSC) or 1(PAL) If selecting VIDEO_CVBS, this parameter is not referenced.) */
00015 /** LCD setting **/
00016 #define LCD_ONOFF              (1)                 /* Select  0(without LCD) or 1(with LCD) */
00017 #define LCD_TYPE               (0)                 /* Select  0(4.3inch) or 1(7.1inch) */
00018 /** JPEG out setting **/
00019 #define JPEG_SEND              (0)                 /* Select  0(JPEG images are not output to PC) or 1(JPEG images are output to PC on USB(CDC) for focusing the camera) */
00020 /** Decode hints **/
00021 #define DECODE_HINTS           (DecodeHints::ONED_HINT | DecodeHints::QR_CODE_HINT | DecodeHints::DATA_MATRIX_HINT | DecodeHints::AZTEC_HINT)
00022 /*****************************/
00023 
00024 #if LCD_ONOFF
00025 /** LCD shield config **/
00026 #if (LCD_TYPE == 0)
00027   #include "LCD_shield_config_4_3inch.h"
00028 #else
00029   #include "LCD_shield_config_7_1inch.h"
00030 #endif
00031   #include "AsciiFont.h"
00032 #endif
00033 
00034 #if JPEG_SEND
00035   #include "JPEG_Converter.h"
00036   #include "DisplayApp.h"
00037 #endif
00038 
00039 /** Video and Grapics (GRAPHICS_LAYER_0) parameter **/
00040 /* video input */
00041 #if USE_VIDEO_CH == (0)
00042   #define VIDEO_INPUT_CH       (DisplayBase::VIDEO_INPUT_CHANNEL_0)
00043   #define VIDEO_INT_TYPE       (DisplayBase::INT_TYPE_S0_VFIELD)
00044 #else
00045   #define VIDEO_INPUT_CH       (DisplayBase::VIDEO_INPUT_CHANNEL_1)
00046   #define VIDEO_INT_TYPE       (DisplayBase::INT_TYPE_S1_VFIELD)
00047 #endif
00048 
00049 /* NTSC or PAL */
00050 #if VIDEO_PAL == 0
00051   #define COL_SYS              (DisplayBase::COL_SYS_NTSC_358)
00052 #else
00053   #define COL_SYS              (DisplayBase::COL_SYS_PAL_443)
00054 #endif
00055 
00056 /* Video input */
00057 #define VIDEO_FORMAT           (DisplayBase::VIDEO_FORMAT_YCBCR422)
00058 #define GRAPHICS_FORMAT        (DisplayBase::GRAPHICS_FORMAT_YCBCR422)
00059 #define WR_RD_WRSWA            (DisplayBase::WR_RD_WRSWA_16BIT)
00060 #define FRAME_BUFFER_BYTE_PER_PIXEL   (2u)
00061 
00062 #if VIDEO_INPUT_METHOD == VIDEO_CVBS
00063   #define WAIT_VFIELD_CNT      (2)
00064 #else
00065   #define WAIT_VFIELD_CNT      (1)
00066 #endif
00067 
00068 /* The size of the video input */
00069 #if ((LCD_ONOFF) && (LCD_TYPE == 0))
00070   #define VIDEO_PIXEL_HW       LCD_PIXEL_WIDTH
00071   #define VIDEO_PIXEL_VW       LCD_PIXEL_HEIGHT
00072 #else
00073   #define VIDEO_PIXEL_HW       (640)  /* VGA */
00074   #define VIDEO_PIXEL_VW       (480)  /* VGA */
00075 #endif
00076 
00077 /*! Frame buffer stride: Frame buffer stride should be set to a multiple of 32 or 128
00078     in accordance with the frame buffer burst transfer mode. */
00079 /* FRAME BUFFER Parameter GRAPHICS_LAYER_0 */
00080 #define FRAME_BUFFER_STRIDE    (((VIDEO_PIXEL_HW * FRAME_BUFFER_BYTE_PER_PIXEL) + 31u) & ~31u)
00081 
00082 static DisplayBase Display;
00083 static Timer decode_timer;
00084 
00085 /* 32 bytes aligned */
00086 static uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * VIDEO_PIXEL_VW]__attribute((section("NC_BSS"),aligned(32)));
00087 
00088 static volatile int32_t vfield_count = 0;
00089 static bool graphics_init_end = false;
00090 static int decode_wait_time = 0;
00091 static void (*p_callback_func)(char * addr, int size);
00092 
00093 #if LCD_ONOFF
00094 /****** LCD ******/
00095 static DigitalOut  lcd_pwon(P7_15);
00096 static DigitalOut  lcd_blon(P8_1);
00097 static PwmOut      lcd_cntrst(P8_15);
00098 
00099 static void Init_LCD_Display(void) {
00100     DisplayBase::graphics_error_t error;
00101     DisplayBase::lcd_config_t lcd_config;
00102     PinName lvds_pin[8] = {
00103         /* data pin */
00104         P5_7, P5_6, P5_5, P5_4, P5_3, P5_2, P5_1, P5_0
00105     };
00106 
00107     lcd_pwon = 0;
00108     lcd_blon = 0;
00109     Thread::wait(100);
00110     lcd_pwon = 1;
00111     lcd_blon = 1;
00112 
00113     Display.Graphics_Lvds_Port_Init(lvds_pin, 8);
00114 
00115     /* Graphics initialization process */
00116     lcd_config = LcdCfgTbl_LCD_shield;
00117     error = Display.Graphics_init(&lcd_config);
00118     if (error != DisplayBase::GRAPHICS_OK) {
00119         printf("Line %d, error %d\n", __LINE__, error);
00120         mbed_die();
00121     }
00122     graphics_init_end = true;
00123 }
00124 
00125 static void Start_LCD_Display(uint8_t * p_buf) {
00126     DisplayBase::rect_t rect;
00127 
00128     rect.vs = 0;
00129     rect.vw = VIDEO_PIXEL_VW;
00130     rect.hs = 0;
00131     rect.hw = VIDEO_PIXEL_HW;
00132     Display.Graphics_Read_Setting(
00133         DisplayBase::GRAPHICS_LAYER_0,
00134         (void *)p_buf,
00135         FRAME_BUFFER_STRIDE,
00136         GRAPHICS_FORMAT,
00137         WR_RD_WRSWA,
00138         &rect
00139     );
00140     Display.Graphics_Start(DisplayBase::GRAPHICS_LAYER_0);
00141 }
00142 
00143 #define VIDEO_PIXEL_HW_STR              (VIDEO_PIXEL_HW - 64)
00144 #define VIDEO_PIXEL_VW_STR              (VIDEO_PIXEL_VW - 64)
00145 #define FRAME_BUFFER_BYTE_PER_PIXEL_STR (2u)
00146 #define FRAME_BUFFER_STRIDE_STR         (((VIDEO_PIXEL_HW_STR * FRAME_BUFFER_BYTE_PER_PIXEL_STR) + 31u) & ~31u)
00147 
00148 static uint8_t user_frame_buffer_string[FRAME_BUFFER_STRIDE_STR * VIDEO_PIXEL_VW_STR]__attribute((section("NC_BSS"),aligned(32)));
00149 static AsciiFont ascii_font(user_frame_buffer_string, VIDEO_PIXEL_HW_STR, VIDEO_PIXEL_VW_STR, FRAME_BUFFER_STRIDE_STR, FRAME_BUFFER_BYTE_PER_PIXEL_STR);
00150 static bool      string_draw;
00151 
00152 static void decode_string_init(void) {
00153     DisplayBase::rect_t rect;
00154 
00155     /* The layer by which the touch panel location is drawn */
00156     ascii_font.Erase(0x00000000);  /* rrrrGBAR (r:Reserve G:Green B:Blue A:Alpha R:Red */
00157     rect.vs = 32;
00158     rect.vw = VIDEO_PIXEL_VW_STR;
00159     rect.hs = 32;
00160     rect.hw = VIDEO_PIXEL_HW_STR;
00161     Display.Graphics_Read_Setting(
00162         DisplayBase::GRAPHICS_LAYER_1,
00163         (void *)user_frame_buffer_string,
00164         FRAME_BUFFER_STRIDE_STR,
00165         DisplayBase::GRAPHICS_FORMAT_ARGB4444,
00166         DisplayBase::WR_RD_WRSWA_32_16BIT,
00167         &rect
00168     );
00169     Display.Graphics_Start(DisplayBase::GRAPHICS_LAYER_1);
00170     string_draw = false;
00171 }
00172 
00173 static void decode_string_disp(char ** decode_str) {
00174     if ((decode_str != NULL) && (*decode_str != NULL)) {
00175         /* Drow string */
00176         ascii_font.Erase(0x00000090);  /* rrrrGBAR (r:Reserve G:Green B:Blue A:Alpha R:Red */
00177         int rest_size = strlen(*decode_str);
00178         int draw_idx = 0;
00179         int draw_size;
00180         int draw_line = 0;
00181 
00182         while (rest_size > 0) {
00183             draw_size = ascii_font.DrawStr(*decode_str + draw_idx, 6, 5 + (18 * draw_line), 0x0000ffff, 2);
00184             if (draw_size <= 0) {
00185                 break;
00186             }
00187             rest_size -= draw_size;
00188             draw_idx += draw_size;
00189             draw_line++;
00190         }
00191         string_draw = true;
00192     } else {
00193         if (string_draw != false) {
00194             /* Clear string */
00195             ascii_font.Erase(0x00000000);  /* rrrrGBAR (r:Reserve G:Green B:Blue A:Alpha R:Red */
00196             string_draw = false;
00197         }
00198     }
00199 }
00200 #endif // LCD_ONOFF
00201 
00202 #if JPEG_SEND
00203 /****** Jpeg Send ******/
00204 #define JPEG_ENC_MAX_SIZE      (1024 * 63)
00205 #define JPEG_SIGNAL_CAP_COMP   (1L)
00206 
00207 #define JPEGSEND_STB           (0)
00208 #define JPEGSEND_ENC           (1)
00209 
00210 static Thread jpegsendTask(osPriorityAboveNormal, 2048);
00211 static DisplayApp  display_app;
00212 static uint8_t JpegBuffer[JPEG_ENC_MAX_SIZE]__attribute((section("NC_BSS"),aligned(8)));  //8 bytes aligned!;
00213 volatile static uint32_t jpegsend_status = JPEGSEND_STB;
00214 
00215 static void jpegsendTask_main( void ) {
00216     JPEG_Converter Jcu;
00217     size_t jcu_encode_size;
00218 
00219     while (1) {
00220         Thread::signal_wait(JPEG_SIGNAL_CAP_COMP, 80);
00221         jpegsend_status = JPEGSEND_ENC;
00222 
00223         /* JPEG Enc Start */
00224         JPEG_Converter::bitmap_buff_info_t bitmap_buff_info;
00225         JPEG_Converter::encode_options_t   encode_options;
00226         bitmap_buff_info.width              = VIDEO_PIXEL_HW;
00227         bitmap_buff_info.height             = VIDEO_PIXEL_VW;
00228         bitmap_buff_info.format             = JPEG_Converter::WR_RD_YCbCr422;
00229         bitmap_buff_info.buffer_address     = (void *)user_frame_buffer0;
00230         encode_options.encode_buff_size     = sizeof(JpegBuffer);
00231         encode_options.p_EncodeCallBackFunc = NULL;
00232         encode_options.input_swapsetting    = JPEG_Converter::WR_RD_WRSWA_16_8BIT;
00233         jcu_encode_size = 0;
00234         if (Jcu.encode(&bitmap_buff_info, JpegBuffer, &jcu_encode_size, &encode_options) != JPEG_Converter::JPEG_CONV_OK) {
00235             jcu_encode_size = 0;
00236         }
00237 
00238         /* JPEG Data Send */
00239         if ((jcu_encode_size > 256) && (jcu_encode_size < JPEG_ENC_MAX_SIZE)) {
00240             display_app.SendJpeg(JpegBuffer, jcu_encode_size);
00241         }
00242         jpegsend_status = JPEGSEND_STB;
00243     }
00244 }
00245 
00246 static void jpegsendTask_init( void ) {
00247     jpegsendTask.start(jpegsendTask_main);
00248 }
00249 
00250 static void jpegsend_cap_comp( void ) {
00251     if (jpegsend_status == JPEGSEND_STB) {
00252         jpegsendTask.signal_set(JPEG_SIGNAL_CAP_COMP);
00253     }
00254 }
00255 #endif // JPEG_SEND
00256 
00257 /****** Video ******/
00258 static void IntCallbackFunc_Vfield(DisplayBase::int_type_t int_type) {
00259     /* Interrupt callback function for Vfield interruption */
00260     if (vfield_count > 0) {
00261         vfield_count--;
00262     }
00263 #if JPEG_SEND
00264     jpegsend_cap_comp();
00265 #endif // JPEG_SEND
00266 }
00267 
00268 static void Wait_Vfield(const int32_t wait_count) {
00269     /* Wait for the specified number of times Vsync occurs */
00270     vfield_count = wait_count;
00271     while (vfield_count > 0) {
00272         Thread::wait(1);
00273     }
00274 }
00275 
00276 static void Init_Video(void) {
00277     DisplayBase::graphics_error_t error;
00278 
00279     /* Graphics initialization process */
00280     if (graphics_init_end == false) {
00281         /* When not initializing LCD, this processing is needed. */
00282         error = Display.Graphics_init(NULL);
00283         if (error != DisplayBase::GRAPHICS_OK) {
00284             printf("Line %d, error %d\n", __LINE__, error);
00285             mbed_die();
00286         }
00287         graphics_init_end = true;
00288     }
00289 
00290 #if VIDEO_INPUT_METHOD == VIDEO_CVBS
00291     error = Display.Graphics_Video_init( DisplayBase::INPUT_SEL_VDEC, NULL);
00292     if( error != DisplayBase::GRAPHICS_OK ) {
00293         printf("Line %d, error %d\n", __LINE__, error);
00294         mbed_die();
00295     }
00296 #elif VIDEO_INPUT_METHOD == VIDEO_CMOS_CAMERA
00297     DisplayBase::video_ext_in_config_t ext_in_config;
00298     PinName cmos_camera_pin[11] = {
00299         /* data pin */
00300         P2_7, P2_6, P2_5, P2_4, P2_3, P2_2, P2_1, P2_0,
00301         /* control pin */
00302         P10_0,      /* DV0_CLK   */
00303         P1_0,       /* DV0_Vsync */
00304         P1_1        /* DV0_Hsync */
00305     };
00306 
00307     /* MT9V111 camera input config */
00308     ext_in_config.inp_format     = DisplayBase::VIDEO_EXTIN_FORMAT_BT601; /* BT601 8bit YCbCr format */
00309     ext_in_config.inp_pxd_edge   = DisplayBase::EDGE_RISING;              /* Clock edge select for capturing data          */
00310     ext_in_config.inp_vs_edge    = DisplayBase::EDGE_RISING;              /* Clock edge select for capturing Vsync signals */
00311     ext_in_config.inp_hs_edge    = DisplayBase::EDGE_RISING;              /* Clock edge select for capturing Hsync signals */
00312     ext_in_config.inp_endian_on  = DisplayBase::OFF;                      /* External input bit endian change on/off       */
00313     ext_in_config.inp_swap_on    = DisplayBase::OFF;                      /* External input B/R signal swap on/off         */
00314     ext_in_config.inp_vs_inv     = DisplayBase::SIG_POL_NOT_INVERTED;     /* External input DV_VSYNC inversion control     */
00315     ext_in_config.inp_hs_inv     = DisplayBase::SIG_POL_INVERTED;         /* External input DV_HSYNC inversion control     */
00316     ext_in_config.inp_f525_625   = DisplayBase::EXTIN_LINE_525;           /* Number of lines for BT.656 external input */
00317     ext_in_config.inp_h_pos      = DisplayBase::EXTIN_H_POS_CRYCBY;       /* Y/Cb/Y/Cr data string start timing to Hsync reference */
00318     ext_in_config.cap_vs_pos     = 6;                                     /* Capture start position from Vsync */
00319     ext_in_config.cap_hs_pos     = 150;                                   /* Capture start position form Hsync */
00320 #if ((LCD_ONOFF) && (LCD_TYPE == 0))
00321     /* The same screen ratio as the screen ratio of the LCD. */
00322     ext_in_config.cap_width      = 640;                                   /* Capture width */
00323     ext_in_config.cap_height     = 363;                                   /* Capture height Max 468[line]
00324                                                                              Due to CMOS(MT9V111) output signal timing and VDC5 specification */
00325 #else
00326     ext_in_config.cap_width      = 640;                                   /* Capture width */
00327     ext_in_config.cap_height     = 468;                                   /* Capture height Max 468[line]
00328                                                                              Due to CMOS(MT9V111) output signal timing and VDC5 specification */
00329 #endif
00330     error = Display.Graphics_Video_init( DisplayBase::INPUT_SEL_EXT, &ext_in_config);
00331     if( error != DisplayBase::GRAPHICS_OK ) {
00332         printf("Line %d, error %d\n", __LINE__, error);
00333         mbed_die();
00334     }
00335 
00336     /* Camera input port setting */
00337     error = Display.Graphics_Dvinput_Port_Init(cmos_camera_pin, 11);
00338     if( error != DisplayBase::GRAPHICS_OK ) {
00339         printf("Line %d, error %d\n", __LINE__, error);
00340         mbed_die();
00341     }
00342 #endif
00343 
00344     /* Interrupt callback function setting (Field end signal for recording function in scaler 0) */
00345     error = Display.Graphics_Irq_Handler_Set(VIDEO_INT_TYPE, 0, IntCallbackFunc_Vfield);
00346     if (error != DisplayBase::GRAPHICS_OK) {
00347         printf("Line %d, error %d\n", __LINE__, error);
00348         mbed_die();
00349     }
00350 }
00351 
00352 static void Start_Video(uint8_t * p_buf) {
00353     DisplayBase::graphics_error_t error;
00354 
00355     /* Video capture setting (progressive form fixed) */
00356     error = Display.Video_Write_Setting(
00357                 VIDEO_INPUT_CH,
00358                 COL_SYS,
00359                 p_buf,
00360                 FRAME_BUFFER_STRIDE,
00361                 VIDEO_FORMAT,
00362                 WR_RD_WRSWA,
00363                 VIDEO_PIXEL_VW,
00364                 VIDEO_PIXEL_HW
00365             );
00366     if (error != DisplayBase::GRAPHICS_OK) {
00367         printf("Line %d, error %d\n", __LINE__, error);
00368         mbed_die();
00369     }
00370 
00371     /* Video write process start */
00372     error = Display.Video_Start(VIDEO_INPUT_CH);
00373     if (error != DisplayBase::GRAPHICS_OK) {
00374         printf("Line %d, error %d\n", __LINE__, error);
00375         mbed_die();
00376     }
00377 
00378     /* Video write process stop */
00379     error = Display.Video_Stop(VIDEO_INPUT_CH);
00380     if (error != DisplayBase::GRAPHICS_OK) {
00381         printf("Line %d, error %d\n", __LINE__, error);
00382         mbed_die();
00383     }
00384 
00385     /* Video write process start */
00386     error = Display.Video_Start(VIDEO_INPUT_CH);
00387     if (error != DisplayBase::GRAPHICS_OK) {
00388         printf("Line %d, error %d\n", __LINE__, error);
00389         mbed_die();
00390     }
00391 }
00392 
00393 /****** zxing_init ******/
00394 void zxing_init(void (*pfunc)(char * addr, int size)) {
00395 
00396 #if JPEG_SEND
00397     jpegsendTask_init();
00398 #endif // JPEG_SEND
00399 #if LCD_ONOFF
00400     /* Initialization of LCD */
00401     Init_LCD_Display();    /* When using LCD, please call before than Init_Video(). */
00402 #endif // LCD_ONOFF
00403     /* Initialization of Video */
00404     Init_Video();
00405 
00406     /* Initialization memory */
00407     memset(user_frame_buffer0, 0, (FRAME_BUFFER_STRIDE * VIDEO_PIXEL_VW));
00408 
00409     /* Start of Video */
00410     Start_Video(user_frame_buffer0);
00411     /* Wait for first video drawing */
00412     Wait_Vfield(WAIT_VFIELD_CNT);
00413 #if LCD_ONOFF
00414     decode_string_init();
00415     /* Start of LCD */
00416     Start_LCD_Display(user_frame_buffer0);
00417     /* Backlight on */
00418     Thread::wait(200);
00419     lcd_cntrst.write(1.0);
00420 #endif // LCD_ONOFF
00421     p_callback_func = pfunc;
00422     decode_timer.reset();
00423     decode_timer.start();
00424 }
00425 
00426 /****** zxing_main ******/
00427 int zxing_loop() {
00428     int decode_result = -1;
00429     vector<Ref<Result> > results;
00430     char ** decode_str = NULL;
00431 
00432     Wait_Vfield(WAIT_VFIELD_CNT);
00433     /* Decode barcode image */
00434     if (decode_timer.read_ms() >= decode_wait_time) {
00435         decode_timer.reset();
00436         DecodeHints hints(DECODE_HINTS);
00437         hints.setTryHarder(false);
00438         decode_result = ex_decode(user_frame_buffer0, (FRAME_BUFFER_STRIDE * VIDEO_PIXEL_VW), VIDEO_PIXEL_HW, VIDEO_PIXEL_VW, &results, hints);
00439         if (decode_result == 0) {
00440             decode_str = (char **)&(results[0]->getText()->getText());
00441             int size = strlen(*decode_str);
00442             if (p_callback_func != NULL) {
00443                 p_callback_func(*decode_str, size);
00444             }
00445             decode_wait_time = 500;
00446         } else {
00447             decode_wait_time = 10;
00448         }
00449 #if LCD_ONOFF
00450         decode_string_disp(decode_str);
00451 #endif // LCD_ONOFF
00452     }
00453 
00454     return decode_result;
00455 }
00456