This is a mbed Client sample where ZXing is incorporated, and works on GR-PEACH and GR-LYCHEE.

Dependencies:   DisplayApp AsciiFont

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 "EasyAttach_CameraAndLCD.h"
00004 #include "ImageReaderSource.h"
00005 #include "AsciiFont.h"
00006 
00007 /**** User Selection *********/
00008 /** JPEG out setting **/
00009 #define JPEG_SEND              (1)                 /* Select  0(JPEG images are not output to PC) or 1(JPEG images are output to PC on USB(CDC) for focusing the camera) */
00010 #define JPEG_ENCODE_QUALITY    (75)                /* JPEG encode quality (min:1, max:75 (Considering the size of JpegBuffer, about 75 is the upper limit.)) */
00011 #define VFIELD_INT_SKIP_CNT    (0)                 /* A guide for GR-LYCHEE.  0:60fps, 1:30fps, 2:20fps, 3:15fps, 4:12fps, 5:10fps */
00012 /** Decode hints **/
00013 #define DECODE_HINTS           (DecodeHints::ONED_HINT | DecodeHints::QR_CODE_HINT | DecodeHints::DATA_MATRIX_HINT | DecodeHints::AZTEC_HINT)
00014 /*****************************/
00015 
00016 /* Video input and LCD layer 0 output */
00017 #define VIDEO_FORMAT           (DisplayBase::VIDEO_FORMAT_YCBCR422)
00018 #define GRAPHICS_FORMAT        (DisplayBase::GRAPHICS_FORMAT_YCBCR422)
00019 //#define WR_RD_WRSWA            (DisplayBase::WR_RD_WRSWA_32_16BIT)
00020 #define WR_RD_WRSWA            (DisplayBase::WR_RD_WRSWA_16BIT)
00021 #define DATA_SIZE_PER_PIC      (2u)
00022 
00023 /*! Frame buffer stride: Frame buffer stride should be set to a multiple of 32 or 128
00024     in accordance with the frame buffer burst transfer mode. */
00025 #if MBED_CONF_APP_LCD
00026   #define VIDEO_PIXEL_HW       LCD_PIXEL_WIDTH   /* QVGA */
00027   #define VIDEO_PIXEL_VW       LCD_PIXEL_HEIGHT  /* QVGA */
00028 #else
00029   #define VIDEO_PIXEL_HW       (640u)  /* VGA */
00030   #define VIDEO_PIXEL_VW       (480u)  /* VGA */
00031 #endif
00032 
00033 #define FRAME_BUFFER_STRIDE    (((VIDEO_PIXEL_HW * DATA_SIZE_PER_PIC) + 31u) & ~31u)
00034 #define FRAME_BUFFER_HEIGHT    (VIDEO_PIXEL_VW)
00035 
00036 DisplayBase Display;
00037 // Timer
00038 static Timer decode_timer;
00039 
00040 #if defined(__ICCARM__)
00041 #pragma data_alignment=32
00042 static uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * FRAME_BUFFER_HEIGHT]@ ".mirrorram";
00043 #else
00044 static uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * FRAME_BUFFER_HEIGHT]__attribute((section("NC_BSS"),aligned(32)));
00045 #endif
00046 
00047 #if JPEG_SEND
00048 #include "JPEG_Converter.h"
00049 #include "DisplayApp.h"
00050 #include "dcache-control.h"
00051 
00052 #if defined(__ICCARM__)
00053 #pragma data_alignment=32
00054 static uint8_t JpegBuffer[2][1024 * 64];
00055 #else
00056 static uint8_t JpegBuffer[2][1024 * 64]__attribute((aligned(32)));
00057 #endif
00058 static size_t jcu_encode_size[2];
00059 static JPEG_Converter Jcu;
00060 static int jcu_buf_index_write = 0;
00061 static int jcu_buf_index_write_done = 0;
00062 static int jcu_buf_index_read = 0;
00063 static volatile int jcu_encoding = 0;
00064 static volatile int image_change = 0;
00065 static DisplayApp  display_app;
00066 static int Vfield_Int_Cnt = 0;
00067 
00068 static int decode_wait_time = 0;
00069 static void (*p_callback_func)(char * addr, int size);
00070 
00071 static void JcuEncodeCallBackFunc(JPEG_Converter::jpeg_conv_error_t err_code) {
00072     if (err_code == JPEG_Converter::JPEG_CONV_OK) {
00073         jcu_buf_index_write_done = jcu_buf_index_write;
00074         image_change = 1;
00075     }
00076     jcu_encoding = 0;
00077 }
00078 
00079 static void snapshot(void) {
00080     while ((jcu_encoding == 1) || (image_change == 0)) {
00081         Thread::wait(1);
00082     }
00083     jcu_buf_index_read = jcu_buf_index_write_done;
00084     image_change = 0;
00085     display_app.SendJpeg(JpegBuffer[jcu_buf_index_read], (int)jcu_encode_size[jcu_buf_index_read]);
00086 }
00087 
00088 static void IntCallbackFunc_Vfield(DisplayBase::int_type_t int_type) {
00089     if (Vfield_Int_Cnt < VFIELD_INT_SKIP_CNT) {
00090         Vfield_Int_Cnt++;
00091         return;
00092     }
00093     Vfield_Int_Cnt = 0;
00094 
00095     //Interrupt callback function
00096     if (jcu_encoding == 0) {
00097         JPEG_Converter::bitmap_buff_info_t bitmap_buff_info;
00098         JPEG_Converter::encode_options_t   encode_options;
00099 
00100         bitmap_buff_info.width              = VIDEO_PIXEL_HW;
00101         bitmap_buff_info.height             = VIDEO_PIXEL_VW;
00102         bitmap_buff_info.format             = JPEG_Converter::WR_RD_YCbCr422;
00103         bitmap_buff_info.buffer_address     = (void *)user_frame_buffer0;
00104 
00105         encode_options.encode_buff_size     = sizeof(JpegBuffer[0]);
00106         encode_options.p_EncodeCallBackFunc = &JcuEncodeCallBackFunc;
00107 //        encode_options.input_swapsetting    = JPEG_Converter::WR_RD_WRSWA_32_16_8BIT;
00108         encode_options.input_swapsetting    = JPEG_Converter::WR_RD_WRSWA_16_8BIT;
00109 
00110         jcu_encoding = 1;
00111         if (jcu_buf_index_read == jcu_buf_index_write) {
00112             jcu_buf_index_write ^= 1;  // toggle
00113         }
00114         jcu_encode_size[jcu_buf_index_write] = 0;
00115         dcache_invalid(JpegBuffer[jcu_buf_index_write], sizeof(JpegBuffer[0]));
00116         if (Jcu.encode(&bitmap_buff_info, JpegBuffer[jcu_buf_index_write],
00117             &jcu_encode_size[jcu_buf_index_write], &encode_options) != JPEG_Converter::JPEG_CONV_OK) {
00118             jcu_encode_size[jcu_buf_index_write] = 0;
00119             jcu_encoding = 0;
00120         }
00121     }
00122 }
00123 #endif
00124 
00125 static void Start_Video_Camera(void) {
00126     // Video capture setting (progressive form fixed)
00127     Display.Video_Write_Setting(
00128         DisplayBase::VIDEO_INPUT_CHANNEL_0,
00129         DisplayBase::COL_SYS_NTSC_358,
00130         (void *)user_frame_buffer0,
00131         FRAME_BUFFER_STRIDE,
00132         VIDEO_FORMAT,
00133         WR_RD_WRSWA,
00134         VIDEO_PIXEL_VW,
00135         VIDEO_PIXEL_HW
00136     );
00137     EasyAttach_CameraStart(Display, DisplayBase::VIDEO_INPUT_CHANNEL_0);
00138 }
00139 
00140 #if MBED_CONF_APP_LCD
00141 static void Start_LCD_Display(void) {
00142     DisplayBase::rect_t rect;
00143 
00144     rect.vs = 0;
00145     rect.vw = LCD_PIXEL_HEIGHT;
00146     rect.hs = 0;
00147     rect.hw = LCD_PIXEL_WIDTH;
00148     Display.Graphics_Read_Setting(
00149         DisplayBase::GRAPHICS_LAYER_0,
00150         (void *)user_frame_buffer0,
00151         FRAME_BUFFER_STRIDE,
00152         GRAPHICS_FORMAT,
00153         WR_RD_WRSWA,
00154         &rect
00155     );
00156     Display.Graphics_Start(DisplayBase::GRAPHICS_LAYER_0);
00157 
00158     Thread::wait(50);
00159     EasyAttach_LcdBacklight(true);
00160 }
00161 
00162 #define VIDEO_PIXEL_HW_STR              (VIDEO_PIXEL_HW - 64)
00163 #define VIDEO_PIXEL_VW_STR              (VIDEO_PIXEL_VW - 64)
00164 #define FRAME_BUFFER_BYTE_PER_PIXEL_STR (2u)
00165 #define FRAME_BUFFER_STRIDE_STR         (((VIDEO_PIXEL_HW_STR * FRAME_BUFFER_BYTE_PER_PIXEL_STR) + 31u) & ~31u)
00166 
00167 static uint8_t user_frame_buffer_string[FRAME_BUFFER_STRIDE_STR * VIDEO_PIXEL_VW_STR]__attribute((section("NC_BSS"),aligned(32)));
00168 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);
00169 static bool      string_draw;
00170 static int error_cnt;
00171 
00172 static void decode_string_init(void) {
00173     DisplayBase::rect_t rect;
00174 
00175     /* The layer by which the touch panel location is drawn */
00176     ascii_font.Erase(0x00000000);  /* rrrrGBAR (r:Reserve G:Green B:Blue A:Alpha R:Red */
00177     rect.vs = 32;
00178     rect.vw = VIDEO_PIXEL_VW_STR;
00179     rect.hs = 32;
00180     rect.hw = VIDEO_PIXEL_HW_STR;
00181     Display.Graphics_Read_Setting(
00182         DisplayBase::GRAPHICS_LAYER_2,
00183         (void *)user_frame_buffer_string,
00184         FRAME_BUFFER_STRIDE_STR,
00185         DisplayBase::GRAPHICS_FORMAT_ARGB4444,
00186         DisplayBase::WR_RD_WRSWA_32_16BIT,
00187         &rect
00188     );
00189     Display.Graphics_Start(DisplayBase::GRAPHICS_LAYER_2);
00190     string_draw = false;
00191     error_cnt = 0;
00192 }
00193 
00194 static void decode_string_disp(char ** decode_str) {
00195     if ((decode_str != NULL) && (*decode_str != NULL)) {
00196         /* Drow string */
00197         ascii_font.Erase(0x00000090);  /* rrrrGBAR (r:Reserve G:Green B:Blue A:Alpha R:Red */
00198         int rest_size = strlen(*decode_str);
00199         int draw_idx = 0;
00200         int draw_size;
00201         int draw_line = 0;
00202 
00203         while (rest_size > 0) {
00204             draw_size = ascii_font.DrawStr(*decode_str + draw_idx, 6, 5 + (18 * draw_line), 0x0000ffff, 2);
00205             if (draw_size <= 0) {
00206                 break;
00207             }
00208             rest_size -= draw_size;
00209             draw_idx += draw_size;
00210             draw_line++;
00211         }
00212         string_draw = true;
00213         error_cnt = 0;
00214     } else {
00215         if (string_draw != false) {
00216             error_cnt++;
00217             if (error_cnt > 15) {
00218                 /* Clear string */
00219                 ascii_font.Erase(0x00000000);  /* rrrrGBAR (r:Reserve G:Green B:Blue A:Alpha R:Red */
00220                 string_draw = false;
00221             }
00222         }
00223     }
00224 }
00225 #endif
00226 
00227 
00228 /****** zxing_init ******/
00229 void zxing_init(void (*pfunc)(char * addr, int size)) {
00230     // Initialize the background to black
00231     for (int i = 0; i < (int)sizeof(user_frame_buffer0); i += 2) {
00232         user_frame_buffer0[i + 0] = 0x10;
00233         user_frame_buffer0[i + 1] = 0x80;
00234     }
00235 
00236 #if MBED_CONF_APP_LCD
00237     EasyAttach_Init(Display, 640, 360);
00238 #else
00239     EasyAttach_Init(Display);
00240 #endif
00241 #if JPEG_SEND
00242     Jcu.SetQuality(JPEG_ENCODE_QUALITY);
00243     // Interrupt callback function setting (Field end signal for recording function in scaler 0)
00244     Display.Graphics_Irq_Handler_Set(DisplayBase::INT_TYPE_S0_VFIELD, 0, IntCallbackFunc_Vfield);
00245 #endif
00246     Start_Video_Camera();
00247 #if MBED_CONF_APP_LCD
00248     decode_string_init();
00249     Start_LCD_Display();
00250 #endif
00251 
00252     p_callback_func = pfunc;
00253     decode_timer.reset();
00254     decode_timer.start();
00255 }
00256 
00257 /****** zxing_main ******/
00258 int zxing_loop() {
00259     int decode_result = -1;
00260     vector<Ref<Result> > results;
00261     char ** decode_str = NULL;
00262 
00263     /* Decode barcode image */
00264     if (decode_timer.read_ms() >= decode_wait_time) {
00265         decode_timer.reset();
00266         DecodeHints hints(DECODE_HINTS);
00267         hints.setTryHarder(false);
00268         decode_result = ex_decode(user_frame_buffer0, (FRAME_BUFFER_STRIDE * VIDEO_PIXEL_VW), VIDEO_PIXEL_HW, VIDEO_PIXEL_VW, &results, hints);
00269         if (decode_result == 0) {
00270             decode_str = (char **)&(results[0]->getText()->getText());
00271             int size = strlen(*decode_str);
00272             if (p_callback_func != NULL) {
00273                 p_callback_func(*decode_str, size);
00274             }
00275             decode_wait_time = 500;
00276         } else {
00277             decode_wait_time = 10;
00278         }
00279 #if MBED_CONF_APP_LCD
00280         decode_string_disp(decode_str);
00281 #endif
00282     }
00283 
00284     return decode_result;
00285 }
00286