Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.cpp
00001 #include "mbed.h" 00002 #include "opencv.hpp" 00003 #include "EasyAttach_CameraAndLCD.h" 00004 #include "dcache-control.h" 00005 #include "AsciiFont.h" 00006 #include "hal/trng_api.h" 00007 #include "oekaki_theme.h" 00008 00009 #define PLOT_INTERVAL (30) 00010 #define DIST_SCALE_FACTOR_X (6.0) 00011 #define DIST_SCALE_FACTOR_Y (6.0) 00012 00013 #define STRING_DISP_TEST (1) 00014 #define DRAW_POINT (3) 00015 #define ERASER_POINT (10) 00016 #define TOUCH_BUFFER_BYTE_PER_PIXEL (2u) 00017 #define TOUCH_BUFFER_STRIDE (((LCD_PIXEL_WIDTH * TOUCH_BUFFER_BYTE_PER_PIXEL) + 31u) & ~31u) 00018 #define COLOR_BLUE cv::Scalar(0,255,0) 00019 00020 /*! Frame buffer stride: Frame buffer stride should be set to a multiple of 32 or 128 00021 in accordance with the frame buffer burst transfer mode. */ 00022 #define VIDEO_PIXEL_HW (160u) /* HQVGA */ 00023 #define VIDEO_PIXEL_VW (120u) /* HQVGA */ 00024 00025 #define FRAME_BUFFER_STRIDE (((VIDEO_PIXEL_HW * 2) + 31u) & ~31u) 00026 #define FRAME_BUFFER_HEIGHT (VIDEO_PIXEL_VW) 00027 00028 #if defined(__ICCARM__) 00029 #pragma data_alignment=32 00030 static uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * FRAME_BUFFER_HEIGHT]@ ".mirrorram"; 00031 static uint8_t user_frame_buffer1[TOUCH_BUFFER_STRIDE * LCD_PIXEL_HEIGHT]@ ".mirrorram"; 00032 #else 00033 static uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * FRAME_BUFFER_HEIGHT]__attribute((section("NC_BSS"),aligned(32))); 00034 static uint8_t user_frame_buffer1[TOUCH_BUFFER_STRIDE * LCD_PIXEL_HEIGHT]__attribute((section("NC_BSS"),aligned(32)));//cameraみたい 00035 #endif 00036 static volatile int Vfield_Int_Cnt = 0; 00037 00038 static InterruptIn skip_btn0(USER_BUTTON0); 00039 static InterruptIn skip_btn1(USER_BUTTON1); 00040 static int clr=0;//カラー選択(0=青、 1=黒(消しゴム)) 00041 static int layer2flg=0; 00042 static int kesiflg=0;//1のとき、消しゴムを使ったあと。 00043 static bool btndownflg=false; 00044 static int16_t RangeCorr(int16_t target ,int16_t uplimit,int16_t lowlimit); 00045 static uint8_t get_random(void); 00046 00047 DisplayBase Display; 00048 DigitalOut led1(LED1); 00049 static Thread mainTask(osPriorityNormal, 1024 * 16); 00050 00051 static void IntCallbackFunc_Vfield(DisplayBase::int_type_t int_type) { 00052 if (Vfield_Int_Cnt > 0) { 00053 Vfield_Int_Cnt--; 00054 } 00055 } 00056 00057 static void wait_new_image(void) { 00058 Vfield_Int_Cnt = 1; 00059 while (Vfield_Int_Cnt > 0) { 00060 ThisThread::sleep_for(1); 00061 } 00062 } 00063 00064 static void Start_Video_Camera(void) { 00065 // Field end signal for recording function in scaler 0 00066 Display.Graphics_Irq_Handler_Set(DisplayBase::INT_TYPE_S0_VFIELD, 0, IntCallbackFunc_Vfield); 00067 00068 // Video capture setting (progressive form fixed) 00069 Display.Video_Write_Setting( 00070 DisplayBase::VIDEO_INPUT_CHANNEL_0, 00071 DisplayBase::COL_SYS_NTSC_358, 00072 (void *)user_frame_buffer0, 00073 FRAME_BUFFER_STRIDE, 00074 DisplayBase::VIDEO_FORMAT_YCBCR422, 00075 DisplayBase::WR_RD_WRSWA_32_16BIT, 00076 VIDEO_PIXEL_VW, 00077 VIDEO_PIXEL_HW 00078 ); 00079 EasyAttach_CameraStart(Display, DisplayBase::VIDEO_INPUT_CHANNEL_0); 00080 } 00081 00082 #if MBED_CONF_APP_LCD 00083 static void Start_LCD_Display(void) { 00084 DisplayBase::rect_t rect; 00085 00086 /* The layer by which the touch panel location is drawn */ 00087 memset(user_frame_buffer1, 0, sizeof(user_frame_buffer1));//framebufferの名前を変えた、 00088 dcache_clean(user_frame_buffer1, sizeof(user_frame_buffer1));//framebufferの名前を変えた、 00089 rect.vs = 0; 00090 rect.vw = LCD_PIXEL_HEIGHT; 00091 rect.hs = 0; 00092 rect.hw = LCD_PIXEL_WIDTH; 00093 Display.Graphics_Read_Setting( 00094 DisplayBase::GRAPHICS_LAYER_0, 00095 (void *)user_frame_buffer1, 00096 TOUCH_BUFFER_STRIDE, 00097 DisplayBase::GRAPHICS_FORMAT_ARGB4444, 00098 DisplayBase::WR_RD_WRSWA_32_16BIT, 00099 &rect 00100 ); 00101 Display.Graphics_Start(DisplayBase::GRAPHICS_LAYER_0); 00102 00103 ThisThread::sleep_for(50); 00104 EasyAttach_LcdBacklight(true); 00105 } 00106 00107 #if STRING_DISP_TEST 00108 //文字列出力 00109 #define STRING_PIXEL_HW (129) 00110 #define STRING_PIXEL_VM (24) 00111 #define STRING_BUFFER_BYTE_PER_PIXEL (2u) 00112 #define STRING_BUFFER_STRIDE (((LCD_PIXEL_WIDTH * STRING_BUFFER_BYTE_PER_PIXEL) + 31u) & ~31u) 00113 00114 #if defined(__ICCARM__) 00115 #pragma data_alignment=32 00116 static uint8_t user_frame_buffer_string[STRING_BUFFER_STRIDE * STRING_PIXEL_VM]; 00117 #else 00118 static uint8_t user_frame_buffer_string[STRING_BUFFER_STRIDE * STRING_PIXEL_VM]__attribute((aligned(32))); 00119 #endif 00120 00121 static void string_task(void){ 00122 DisplayBase::rect_t rect; 00123 00124 memset(user_frame_buffer_string,0,sizeof(user_frame_buffer_string)); 00125 dcache_clean(user_frame_buffer_string,sizeof(user_frame_buffer_string)); 00126 00127 rect.vs = LCD_PIXEL_HEIGHT - STRING_PIXEL_VM - 10; 00128 rect.vw = STRING_PIXEL_VM; 00129 rect.hs = LCD_PIXEL_WIDTH - STRING_PIXEL_HW-10; 00130 rect.hw = STRING_PIXEL_HW; 00131 Display.Graphics_Read_Setting( 00132 DisplayBase::GRAPHICS_LAYER_2, 00133 (void *)user_frame_buffer_string, 00134 STRING_BUFFER_STRIDE, 00135 DisplayBase::GRAPHICS_FORMAT_ARGB4444, 00136 DisplayBase::WR_RD_WRSWA_32_16BIT, 00137 &rect 00138 ); 00139 Display.Graphics_Start(DisplayBase::GRAPHICS_LAYER_2); 00140 00141 AsciiFont ascii_font(user_frame_buffer_string,STRING_PIXEL_HW,STRING_PIXEL_VM, 00142 STRING_BUFFER_STRIDE,STRING_BUFFER_BYTE_PER_PIXEL); 00143 00144 int num=get_random(); 00145 int layer2flg_last = -1; 00146 while(1){ 00147 if(layer2flg_last!=layer2flg){ 00148 if(layer2flg==0){ 00149 ascii_font.DrawStr(ChooseTheme(num), 0, 0 , 0x0000ffff, 2);//白 00150 }else{ 00151 memset(user_frame_buffer_string,0,sizeof(user_frame_buffer_string)); 00152 } 00153 dcache_clean(user_frame_buffer_string,sizeof(user_frame_buffer_string)); 00154 layer2flg_last=layer2flg; 00155 } 00156 ThisThread::sleep_for(50); 00157 } 00158 } 00159 #endif 00160 00161 static void draw_touch_pos(uint8_t * p_buf, int id, int drawpoint,int x, int y) { //バッファ,色,線の太さ,x座標,y座標 00162 int idx_base; 00163 int wk_idx; 00164 int i; 00165 int j; 00166 uint8_t coller_pix[TOUCH_BUFFER_BYTE_PER_PIXEL]; /* ARGB4444 */ 00167 00168 /* A coordinate in the upper left is calculated from a central coordinate. */ 00169 if ((x - (drawpoint / 2)) >= 0) { 00170 x -= (drawpoint / 2); 00171 } 00172 if (x > ((int)LCD_PIXEL_WIDTH - drawpoint)) { 00173 x = ((int)LCD_PIXEL_WIDTH - drawpoint); 00174 } 00175 if ((y - (drawpoint / 2)) >= 0) { 00176 y -= (drawpoint / 2); 00177 } 00178 if (y > ((int)LCD_PIXEL_HEIGHT - drawpoint)) { 00179 y = ((int)LCD_PIXEL_HEIGHT - drawpoint); 00180 } 00181 idx_base = (x + ((int)LCD_PIXEL_WIDTH * y)) * TOUCH_BUFFER_BYTE_PER_PIXEL; 00182 00183 /* Select color */ 00184 if (id == 0) { 00185 /* Blue */ 00186 coller_pix[0] = 0x0F; /* 4:Green 4:Blue */ 00187 coller_pix[1] = 0xF0; /* 4:Alpha 4:Red */ 00188 } else if (id == 1){ 00189 00190 /* black */ 00191 coller_pix[0] = 0x00; /* 4:Green 4:Blue */ 00192 coller_pix[1] = 0x00; /* 4:Alpha 4:Red */ 00193 } else { 00194 /* red */ 00195 coller_pix[0] = 0x01; 00196 coller_pix[1] = 0xFF; 00197 } 00198 00199 /* Drawing */ 00200 for (i = 0; i < drawpoint; i++) { 00201 wk_idx = idx_base + ((int)LCD_PIXEL_WIDTH * TOUCH_BUFFER_BYTE_PER_PIXEL * i); 00202 for (j = 0; j < drawpoint; j++) { 00203 p_buf[wk_idx++] = coller_pix[0]; 00204 p_buf[wk_idx++] = coller_pix[1]; 00205 } 00206 } 00207 } 00208 #endif 00209 00210 static void DrawLine(int32_t x1,int32_t y1,int32_t x2, int32_t y2,int drawpoint){ 00211 int32_t dx=x2-x1; 00212 int32_t dy=y2-y1; 00213 int32_t sx=1; 00214 int32_t sy=1; 00215 int32_t i; 00216 int32_t de; 00217 00218 if(dx<0){ 00219 dx *= -1; 00220 sx *= -1; 00221 } 00222 00223 if(dy<0){ 00224 dy*=-1; 00225 sy*=-1; 00226 } 00227 draw_touch_pos(user_frame_buffer1,clr,drawpoint,x1,y1); 00228 00229 if(dx>dy){ 00230 for(i=dx,de=i/2;i;i--){ 00231 x1+=sx; 00232 de+=dy; 00233 if(de>dx){ 00234 de-=dx; 00235 y1+=sy; 00236 } 00237 draw_touch_pos(user_frame_buffer1,clr,drawpoint,x1,y1); 00238 } 00239 }else{ 00240 for(i=dy,de=i/2;i;i--){ 00241 y1+=sy; 00242 de+=dx; 00243 if(de>dy){ 00244 de-=dy; 00245 x1+=sx; 00246 } 00247 draw_touch_pos(user_frame_buffer1,clr,drawpoint,x1,y1); 00248 } 00249 } 00250 } 00251 00252 void skip_btn_fall0(void){ 00253 btndownflg=true;//ボタンおした 00254 } 00255 00256 void skip_btn_fall1(void){ 00257 clr=(clr+1)%2; //消しゴム(黒色)と青色色分け 00258 if((layer2flg==1 && btndownflg==false)){ 00259 layer2flg=0; 00260 }else{ 00261 layer2flg=1;//非表示 00262 } 00263 } 00264 00265 void skip_btn_rise0(void){ 00266 btndownflg=false;//ボタンはなれた 00267 } 00268 00269 static void main_task(void) { 00270 cv::Mat prev_image; 00271 cv::Mat curr_image; 00272 std::vector<cv::Point2f> prev_pts; 00273 std::vector<cv::Point2f> curr_pts; 00274 cv::Point2f point; 00275 int16_t x = 0; 00276 int16_t y = 0; 00277 00278 EasyAttach_Init(Display); 00279 Start_Video_Camera(); 00280 #if MBED_CONF_APP_LCD 00281 Start_LCD_Display(); 00282 #endif 00283 00284 #if STRING_DISP_TEST 00285 //string 00286 Thread stringTask; 00287 stringTask.start(callback(string_task)); 00288 #endif // STRING_DISP_TEST 00289 00290 // Initialization of optical flow 00291 point.y = (VIDEO_PIXEL_VW / 2) + (PLOT_INTERVAL * 1); 00292 for (int32_t i = 0; i < 3; i++) { 00293 point.x = (VIDEO_PIXEL_HW / 2) - (PLOT_INTERVAL * 1); 00294 for (int32_t j = 0; j < 3; j++) { 00295 prev_pts.push_back(point); 00296 point.x += PLOT_INTERVAL; 00297 } 00298 point.y -= PLOT_INTERVAL; 00299 } 00300 skip_btn0.fall(&skip_btn_fall0); 00301 skip_btn1.fall(&skip_btn_fall1); 00302 skip_btn0.rise(&skip_btn_rise0); //tuika ボタンを離したときに関数を呼び出す 00303 00304 #if MBED_CONF_APP_LCD 00305 int16_t posx=LCD_PIXEL_WIDTH/2; 00306 int16_t posy=LCD_PIXEL_HEIGHT/2; 00307 int16_t prex=0; 00308 int16_t prey=0; 00309 int16_t akax=0; 00310 int16_t akay=0; 00311 00312 while (1) { 00313 // Wait for image input 00314 wait_new_image(); 00315 00316 // Convert from YUV422 to grayscale 00317 cv::Mat img_yuv(VIDEO_PIXEL_VW, VIDEO_PIXEL_HW, CV_8UC2, user_frame_buffer0); 00318 cv::cvtColor(img_yuv, curr_image, cv::COLOR_YUV2GRAY_YUY2); 00319 00320 point = cv::Point2f(0, 0); 00321 if ((!curr_image.empty()) && (!prev_image.empty())) { 00322 // Optical flow 00323 std::vector<uchar> status; 00324 std::vector<float> err; 00325 cv::calcOpticalFlowPyrLK(prev_image, curr_image, prev_pts, curr_pts, status, err, cv::Size(21, 21), 0); 00326 00327 // Setting movement distance of feature point 00328 std::vector<cv::Scalar> samples; 00329 for (size_t i = 0; i < (size_t)status.size(); i++) { 00330 if (status[i]) { 00331 cv::Point2f vec = curr_pts[i] - prev_pts[i]; 00332 cv::Scalar sample = cv::Scalar(vec.x, vec.y); 00333 samples.push_back(sample); 00334 } 00335 } 00336 00337 // Mean and standard deviation 00338 if (samples.size() >= 6) { 00339 cv::Scalar mean; 00340 cv::Scalar stddev; 00341 cv::meanStdDev((cv::InputArray)samples, mean, stddev); 00342 //printf("%d, stddev=%lf, %lf\r\n", samples.size(), stddev[0], stddev[1]); // for debug 00343 if ((stddev[0] < 10.0) && (stddev[1] < 10.0)) { 00344 point.x = mean[0]; 00345 point.y = mean[1]; 00346 } 00347 } 00348 } 00349 cv::swap(prev_image, curr_image); 00350 00351 x = (int16_t)(point.x * DIST_SCALE_FACTOR_X) *- 1 * 0.8; 00352 y = (int16_t)(point.y * DIST_SCALE_FACTOR_Y) * -1 * 0.8; 00353 00354 if(btndownflg==true){ 00355 //xとyは移動量なので、現在地を算出する 00356 //その前に現在地を保存 00357 prex=posx;//移動前 00358 prey=posy;//移動前 00359 posx+=x;//移動後 00360 posy+=y;//移動後 00361 } 00362 //displayの外にはみでていたらdisplayの枠に値を矯正 00363 posx=RangeCorr(posx,(int)LCD_PIXEL_WIDTH,0); 00364 posy=RangeCorr(posy,(int)LCD_PIXEL_HEIGHT,0); 00365 00366 #endif 00367 if ((x != 0) || (y != 0)) { 00368 led1 = 1; 00369 //printf("x=%d, y=%d\r\n", x, y); // for debug 00370 #if MBED_CONF_APP_LCD 00371 if(btndownflg==true){//ub0のボタンが奇数回(1,,3, 5,・・・)押下されたら、線を描画する。(on,offスイッチ) 00372 if(clr==1){ 00373 //円を描画して消す 00374 draw_touch_pos(user_frame_buffer1,clr,ERASER_POINT,prex,prey); //前の座標を消去 00375 DrawLine(prex,prey,posx,posy,ERASER_POINT); 00376 draw_touch_pos(user_frame_buffer1,2,ERASER_POINT,posx,posy); //赤いカーソルの描画 00377 akax=posx; 00378 akay=posy; 00379 00380 kesiflg=1;//消しゴムモードになりました的な 00381 00382 }else{ 00383 if(kesiflg==1){//消しゴムモード→ペンモードに変わったとき、カーソルがディスプレイに残るので黒で上塗りして消す 00384 draw_touch_pos(user_frame_buffer1,1,ERASER_POINT,akax,akay); 00385 kesiflg=0; 00386 } 00387 draw_touch_pos(user_frame_buffer1,clr/*黒*/,DRAW_POINT,posx,posy); //ペン 00388 DrawLine(prex,prey,posx,posy,DRAW_POINT); 00389 } 00390 }/*else if(kesiflg==1){//消しゴムモードでUserBottun0を押すとカーソルが残ってしまうので、黒を上塗りして消す 00391 draw_touch_pos(user_frame_buffer1,1,ERASER_POINT,akax,akay); 00392 kesiflg=0; 00393 }*/ 00394 00395 00396 #endif 00397 } else { 00398 led1 = 0; 00399 } 00400 } 00401 } 00402 00403 #if MBED_CONF_APP_LCD 00404 //範囲の修正 00405 int16_t RangeCorr(int16_t target ,int16_t uplimit,int16_t lowlimit){ 00406 if(target>=lowlimit && target<=uplimit){ //もし範囲内だったら 00407 return target;//そのまま返す 00408 }else if(target>uplimit){ //上限より値が大きかったら 00409 return uplimit; //上限の値を返す 00410 }else{ //下限より小さかったら 00411 return lowlimit; //下限の値を返す 00412 } 00413 } 00414 #endif 00415 00416 00417 uint8_t get_random(void){ 00418 size_t olen; 00419 uint8_t data; 00420 trng_t trng_obj; 00421 static bool init_flg = false; 00422 00423 trng_init(&trng_obj); 00424 if (init_flg == false) { 00425 init_flg = true; 00426 trng_get_bytes(&trng_obj, &data, 1, &olen); 00427 } 00428 trng_get_bytes(&trng_obj, &data, 1, &olen); 00429 trng_free(&trng_obj); 00430 return data; 00431 } 00432 00433 int main(void) { 00434 mainTask.start(callback(main_task)); 00435 mainTask.join(); 00436 00437 } 00438
Generated on Thu Jul 14 2022 00:32:37 by
1.7.2