mbed Paint for the RA8875 display with based touch screen.
Dependencies: menu mbed RA8875
main.cpp
00001 /// mPaint is a simple drawing program, used to explore the touch 00002 /// APIs of the RA8875 display library. 00003 /// 00004 /// @note Copyright © 2015 by Smartware Computing, all rights reserved. 00005 /// Individuals may use this application for evaluation or non-commercial 00006 /// purposes. Within this restriction, changes may be made to this application 00007 /// as long as this copyright notice is retained. The user shall make 00008 /// clear that their work is a derived work, and not the original. 00009 /// Users of this application and sources accept this application "as is" and 00010 /// shall hold harmless Smartware Computing, for any undesired results while 00011 /// using this application - whether real or imagined. 00012 /// 00013 /// @author David Smart, Smartware Computing 00014 // 00015 // 00016 #include "mbed.h" // tested with v112 00017 #include "RA8875.h" // tested with v102 00018 #include "menu.h" // v3 00019 00020 #define DEBUG "mPaint" 00021 // ... 00022 // INFO("Stuff to show %d", var); // new-line is automatically appended 00023 // 00024 #if (defined(DEBUG) && !defined(TARGET_LPC11U24)) 00025 #define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00026 #define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00027 #define ERR(x, ...) std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00028 #else 00029 #define INFO(x, ...) 00030 #define WARN(x, ...) 00031 #define ERR(x, ...) 00032 #define HexDump(a, b, c) 00033 #endif 00034 00035 // Define this for 800x480 panel, undefine for 480x272 00036 //#define BIG_SCREEN 00037 00038 // Define this for Cap touch panel, undefine for resistive 00039 //#define CAP_TOUCH 00040 00041 #ifdef CAP_TOUCH 00042 RA8875 lcd(p5, p6, p7, p12, NC, p9,p10,p13, "tft"); // SPI:{MOSI,MISO,SCK,/ChipSelect,/reset}, I2C:{SDA,SCL,/IRQ}, name 00043 #else 00044 RA8875 lcd(p5, p6, p7, p12, NC, "tft"); // SPI:{MOSI,MISO,SCK,/ChipSelect,/reset}, name 00045 // LocalFileSystem local("local"); // if not otherwise needed; access to calibration file for resistive touch. 00046 #endif 00047 00048 #define PC_BAUD 460800 // I like the serial communications to be very fast 00049 00050 // // // // // // // // // // // // // // // // // // // // // // // // 00051 // End of Configuration Section 00052 // // // // // // // // // // // // // // // // // // // // // // // // 00053 00054 #ifdef BIG_SCREEN 00055 #define LCD_W 800 00056 #define LCD_H 480 00057 #define LCD_C 8 // color - bits per pixel 00058 #define DEF_RADIUS 50 // default radius of the fingerprint 00059 #define BL_NORM 25 // Backlight Normal setting (0 to 255) 00060 #else 00061 #define LCD_W 480 00062 #define LCD_H 272 00063 #define LCD_C 8 // color - bits per pixel 00064 #define DEF_RADIUS 20 // default radius of the fingerprint 00065 #define BL_NORM 25 // Backlight Normal setting (0 to 255) 00066 #endif 00067 00068 // A monitor port for the SW developer. 00069 Serial pc(USBTX, USBRX); 00070 00071 LocalFileSystem local("local"); 00072 00073 // list of tools (dots, lines, joined lines). 00074 typedef enum { 00075 dot, // draw dots at the point 00076 line, // connected line from touch(point) to release(point) 00077 join // connected lines while held(point) 00078 } tooltype_t; // what tool are we using to draw 00079 00080 color_t rgb = Black; // the composite color value to draw in. 00081 uint8_t rgbVal[3] = { 0, 0, 0 }; // hosts each of the individual values 00082 uint32_t pensize = 1; // pensize is user selectable within a small range. 00083 tooltype_t selectedtooltype = dot; // 0:dot, 1:line, 2:join 00084 point_t origin = { 0, 0}; // tracks origin when drawing a line 00085 00086 // 0 200 400 500 600 700 800 00087 // | | | | | | | | | 00088 // 0 100 200 300 400 500 00089 // | | | | | | 00090 // +---------------------------------------------------+ 0 00091 // | File Edit Pen Tools [smpl](o) [rrr][ggg][bbb] | 00092 // +---------------------------------------------------+ 00093 // | | 16 32 00094 // | canvas | 00095 // | | 00096 // | | 00097 // | | 00098 // | | 00099 // | | 00100 // | | 00101 // | | 00102 // | | 00103 // +---------------------------------------------------+ 255 463 00104 // | (xxx,yyy) - (xxx,yyy) rgb (RR,GG,BB) | 00105 // +---------------------------------------------------+ 271 479 00106 // 0 479 00107 // 0 799 00108 00109 // Adjust the following if using the 800x480 v 480x272 display 00110 #if LCD_W == 800 00111 const rect_t RGBList[] = { // regions on the display for special tools 00112 { 425,0, 425+50,30 }, // show selected color 00113 { 500,0, 500+80,30 }, // R 00114 { 600,0, 600+80,30 }, // G 00115 { 700,0, 700+80,30 }, // B 00116 }; 00117 const rect_t canvas_rect = { // the drawing surface 00118 0,32, LCD_W-1,LCD_H-1 00119 }; 00120 #else 00121 const rect_t RGBList[] = { // regions on the display for special tools 00122 { 249,0, 249+50,15 }, // show selected color 00123 { 309,0, 309+50,15 }, // R 00124 { 369,0, 369+50,15 }, // G 00125 { 429,0, 429+50,15 }, // B 00126 }; 00127 const rect_t canvas_rect = { // the drawing surface 00128 0,16, LCD_W-1,LCD_H-1 00129 }; 00130 #endif 00131 00132 00133 // File Pen Tools 00134 // New... Pensize 1 Dot 00135 // Save... Pensize 2 Line 00136 // Calibrate Pensize 4 00137 // Reset Pensize 6 00138 // Pensize 8 00139 // 00140 Menu::post_fnc_action_t File(uint32_t v); 00141 Menu::post_fnc_action_t File_New(uint32_t v); 00142 Menu::post_fnc_action_t File_Save(uint32_t v); 00143 Menu::post_fnc_action_t File_Save_All(uint32_t v); 00144 Menu::post_fnc_action_t File_Cal(uint32_t v); 00145 Menu::post_fnc_action_t File_Reset(uint32_t v); 00146 Menu::post_fnc_action_t Edit(uint32_t v); 00147 Menu::post_fnc_action_t Edit_Clear(uint32_t v); 00148 Menu::post_fnc_action_t Tools(uint32_t v); 00149 Menu::post_fnc_action_t Tools_Type(uint32_t v); 00150 Menu::post_fnc_action_t PenSize(uint32_t v); 00151 Menu::post_fnc_action_t HideMenu(uint32_t v); 00152 00153 // Some APIs 00154 extern "C" void mbed_reset(); 00155 int GetScreenCapture(void); 00156 void CalibrateTS(void); 00157 void ShowSampleRGB(void); 00158 void InitDisplay(void); 00159 00160 Menu::menu_item_t file_menu[] = { 00161 // Prompt, onPress, onHold, OnRelease, parameter, child menu 00162 { "New...", File_New, NULL, NULL, 0, NULL }, 00163 { "Save...", File_Save, NULL, NULL, 0, NULL }, 00164 { "Save all", File_Save_All, NULL, NULL, 0, NULL }, 00165 { "Calibrate", File_Cal, NULL, NULL, 0, NULL }, 00166 { "Reset", NULL, NULL, File_Reset, 0, NULL }, 00167 { NULL, NULL, NULL, NULL, 0, NULL }, 00168 }; 00169 00170 Menu::menu_item_t pen_menu[] = { 00171 { "1 pix", NULL, NULL, PenSize, 1, NULL }, 00172 { "2 pix", NULL, NULL, PenSize, 2, NULL }, 00173 { "4 pix", NULL, NULL, PenSize, 4, NULL }, 00174 { "6 pix", NULL, NULL, PenSize, 6, NULL }, 00175 { "8 pix", NULL, NULL, PenSize, 8, NULL }, 00176 { NULL, NULL, NULL, NULL, 0, NULL }, 00177 }; 00178 00179 Menu::menu_item_t tools_menu[] = { 00180 { "point", NULL, NULL, Tools_Type, dot, NULL }, 00181 { "line", NULL, NULL, Tools_Type, line, NULL }, 00182 { "join", NULL, NULL, Tools_Type, join, NULL }, 00183 { NULL, NULL, NULL, NULL, 0, NULL }, 00184 }; 00185 00186 Menu::menu_item_t menudata[] = { 00187 { "File", File, NULL, NULL, 0, file_menu }, 00188 { "Pen", NULL, NULL, NULL, 0, pen_menu }, 00189 { "Tools", NULL, NULL, NULL, 0, tools_menu }, 00190 { "Hide", NULL, NULL, HideMenu, 0, NULL }, 00191 { NULL, NULL, NULL, NULL, 0, NULL }, 00192 }; 00193 00194 Menu menu(lcd, menudata); 00195 00196 Menu::post_fnc_action_t File(uint32_t v) 00197 { 00198 (void)v; 00199 INFO("File"); 00200 return Menu::no_action; 00201 } 00202 Menu::post_fnc_action_t File_New(uint32_t v) 00203 { 00204 (void)v; 00205 INFO("File_New"); 00206 InitDisplay(); 00207 return Menu::no_action; 00208 } 00209 Menu::post_fnc_action_t File_Save(uint32_t v) 00210 { 00211 (void)v; 00212 INFO("File_Save"); 00213 RA8875::LayerMode_T l = lcd.GetLayerMode(); 00214 lcd.SetLayerMode(RA8875::ShowLayer0); 00215 GetScreenCapture(); 00216 lcd.SetLayerMode(RA8875::TransparentMode); 00217 return Menu::close_menu; 00218 } 00219 Menu::post_fnc_action_t File_Save_All(uint32_t v) 00220 { 00221 (void)v; 00222 INFO("File_Save_All"); 00223 GetScreenCapture(); 00224 return Menu::close_menu; 00225 } 00226 Menu::post_fnc_action_t File_Cal(uint32_t v) 00227 { 00228 (void)v; 00229 INFO("Tools_Cal"); 00230 CalibrateTS(); 00231 return Menu::no_action; 00232 } 00233 Menu::post_fnc_action_t File_Reset(uint32_t v) 00234 { 00235 (void)v; 00236 INFO("rebooting now..."); 00237 wait_ms(1000); 00238 mbed_reset(); 00239 return Menu::no_action; 00240 } 00241 Menu::post_fnc_action_t Edit(uint32_t v) 00242 { 00243 (void)v; 00244 INFO("Edit"); 00245 return Menu::no_action; 00246 } 00247 Menu::post_fnc_action_t Tools(uint32_t v) 00248 { 00249 (void)v; 00250 INFO("Tools"); 00251 return Menu::no_action; 00252 } 00253 Menu::post_fnc_action_t PenSize(uint32_t v) 00254 { 00255 pensize = v; 00256 if (pensize < 1) 00257 pensize = 1; 00258 else if (pensize > 8) 00259 pensize = 8; 00260 INFO("PenSize(%d)", pensize); 00261 ShowSampleRGB(); 00262 return Menu::close_menu; 00263 } 00264 Menu::post_fnc_action_t Tools_Type(uint32_t v) 00265 { 00266 switch (v) { 00267 case dot: 00268 case line: 00269 case join: 00270 selectedtooltype = (tooltype_t)v; 00271 break; 00272 default: 00273 break; 00274 } 00275 ShowSampleRGB(); 00276 return Menu::close_menu; 00277 } 00278 Menu::post_fnc_action_t HideMenu(uint32_t v) 00279 { 00280 (void)v; 00281 return Menu::close_menu; 00282 } 00283 00284 void ShowSampleRGB(void) 00285 { 00286 loc_t middle = (RGBList[0].p1.y + RGBList[0].p2.y)/2; 00287 lcd.fillrect(RGBList[0], Black); 00288 if (selectedtooltype == dot) { 00289 lcd.fillcircle((RGBList[0].p1.x + RGBList[0].p2.x)/2, 00290 middle, pensize, rgb); 00291 } else { 00292 lcd.fillrect(RGBList[0], rgb); 00293 } 00294 } 00295 00296 void CalibrateTS(void) 00297 { 00298 FILE * fh; 00299 tpMatrix_t matrix; 00300 RetCode_t r; 00301 00302 r = lcd.TouchPanelCalibrate("Calibrate the touch panel", &matrix); 00303 INFO(" ret: %d", r); 00304 if (r == noerror) { 00305 fh = fopen("/local/tpcal.cfg", "wb"); 00306 if (fh) { 00307 fwrite(&matrix, sizeof(tpMatrix_t), 1, fh); 00308 fclose(fh); 00309 INFO(" tp cal written."); 00310 } else { 00311 WARN(" couldn't open tpcal file."); 00312 } 00313 } else { 00314 ERR("error return: %d", r); 00315 } 00316 } 00317 00318 00319 void InitTS(void) 00320 { 00321 FILE * fh; 00322 tpMatrix_t matrix; 00323 00324 fh = fopen("/local/tpcal.cfg", "rb"); 00325 if (fh) { 00326 fread(&matrix, sizeof(tpMatrix_t), 1, fh); 00327 fclose(fh); 00328 lcd.TouchPanelSetMatrix(&matrix); 00329 INFO(" tp cal loaded."); 00330 } else { 00331 CalibrateTS(); 00332 } 00333 } 00334 00335 00336 void InitDisplay(void) 00337 { 00338 lcd.SelectDrawingLayer(CANVAS); 00339 lcd.cls(); 00340 lcd.foreground(Blue); 00341 lcd.background(Black); 00342 } 00343 00344 int GetScreenCapture(void) 00345 { 00346 char fqfn[50]; 00347 int i = 0; 00348 00349 INFO("Screen Capture... "); 00350 for (i=1; i< 100; i++) { 00351 snprintf(fqfn, sizeof(fqfn), "/local/Screen%02d.bmp", i); 00352 FILE * fh = fopen(fqfn, "rb"); 00353 if (!fh) { 00354 INFO("Saving as %s", fqfn); 00355 lcd.PrintScreen(0,0,lcd.width(),lcd.height(),fqfn); 00356 INFO(" as /local/Screen%02d.bmp", i); 00357 return i; 00358 } else { 00359 fclose(fh); // close this and try the next 00360 } 00361 } 00362 return 0; 00363 } 00364 00365 void ShowRGBSelectors(void) 00366 { 00367 uint16_t curLayer = lcd.GetDrawingLayer(); 00368 lcd.SelectDrawingLayer(MENUS); 00369 lcd.fillrect(RGBList[1], Red); 00370 lcd.fillrect(RGBList[2], Green); 00371 lcd.fillrect(RGBList[3], Blue); 00372 lcd.SelectDrawingLayer(curLayer); 00373 } 00374 00375 bool SeeIfUserSelectingRGBValues(point_t p, TouchCode_t touchcode) 00376 { 00377 static bool wasIn = false; 00378 00379 // See if the touch is setting new RGB values 00380 for (int i=1; i<=3; i++) { 00381 if (lcd.Intersect(RGBList[i], p)) { 00382 uint8_t mag = (255 * (p.x - RGBList[i].p1.x)) / (RGBList[i].p2.x - RGBList[i].p1.x); 00383 wasIn = true; 00384 if (touchcode == touch) 00385 menu.Show(); 00386 else if (touchcode == release) 00387 menu.Hide(); 00388 rgbVal[i-1] = mag; 00389 // update the RGB values 00390 lcd.SelectDrawingLayer(MENUS); 00391 lcd.SetTextCursor(lcd.width() - 10*lcd.fontwidth(), lcd.height() - lcd.fontheight()); 00392 lcd.foreground(Blue); 00393 lcd.printf("(%02X,%02X,%02X)", rgbVal[0], rgbVal[1], rgbVal[2]); 00394 // show sample 00395 rgb = RGB(rgbVal[0], rgbVal[1], rgbVal[2]); 00396 ShowSampleRGB(); 00397 // 00398 lcd.SelectDrawingLayer(CANVAS); 00399 lcd.foreground(rgb); 00400 return true; 00401 } 00402 } 00403 if (wasIn) 00404 menu.Hide(); 00405 return false; 00406 } 00407 00408 int sgn(int x) 00409 { 00410 if (sgn < 0) 00411 return -1; 00412 else if (sgn > 0) 00413 return 1; 00414 else 00415 return 0; 00416 } 00417 00418 00419 00420 void SeeIfUserDrawingOnCanvas(point_t p, TouchCode_t touchcode) 00421 { 00422 if (lcd.Intersect(canvas_rect, p)) { 00423 switch (selectedtooltype) { 00424 case dot: 00425 lcd.fillcircle(p, (pensize == 1) ? pensize : pensize/2, rgb); 00426 break; 00427 case line: 00428 if (touchcode == touch) { 00429 lcd.fillcircle(p, 1, rgb); 00430 origin = p; 00431 INFO("Origin @ (%3d,%3d)", p.x, p.y); 00432 } else if (touchcode == release) { 00433 lcd.ThickLine(origin, p, pensize, rgb); 00434 } 00435 break; 00436 case join: 00437 if (touchcode == touch) { 00438 lcd.fillcircle(p, 1, rgb); 00439 origin = p; 00440 INFO("Origin @ (%3d,%3d)", p.x, p.y); 00441 } else if (touchcode == release) { 00442 lcd.ThickLine(origin, p, pensize, rgb); 00443 } else if (touchcode == held) { 00444 lcd.ThickLine(origin, p, pensize, rgb); 00445 origin = p; 00446 INFO(" held @ (%3d,%3d)", p.x, p.y); 00447 } 00448 break; 00449 default: 00450 break; 00451 } 00452 } 00453 } 00454 00455 00456 int main() 00457 { 00458 pc.baud(460800); // I like a snappy terminal, so crank it up! 00459 pc.printf("\r\nRA8875 Menu - Build " __DATE__ " " __TIME__ "\r\n"); 00460 00461 INFO("Turning on display"); 00462 lcd.init(LCD_W,LCD_H,LCD_C); 00463 lcd.TouchPanelInit(); 00464 lcd.frequency(10000000); 00465 lcd.SetTextFontSize(2); 00466 #ifndef CAP_TOUCH 00467 InitTS(); // resistive touch calibration 00468 #endif 00469 InitDisplay(); 00470 menu.init(); 00471 ShowRGBSelectors(); 00472 00473 INFO("processing loop..."); 00474 00475 for (;;) { 00476 point_t p; 00477 TouchCode_t touchcode = lcd.TouchPanelReadable(&p); 00478 00479 if (touchcode != no_touch) { 00480 //int curLayer = lcd.GetDrawingLayer(); 00481 // This is nice feedback, but certainly slows the drawing. 00482 //lcd.SelectDrawingLayer(MENUS); 00483 //lcd.foreground(Blue); 00484 //lcd.SetTextCursor(0, lcd.height() - 16); 00485 //lcd.printf("(%3d,%3d) - (%3d,%3d)", origin.x, origin.y, p.x, p.y); 00486 //lcd.SelectDrawingLayer(curLayer); 00487 00488 bool menuHandledIt = menu.HandledTouch(p, touchcode); 00489 if (menuHandledIt) { 00490 // menu handled it 00491 } else if (SeeIfUserSelectingRGBValues(p, touchcode)) { 00492 // that handled it. 00493 } else { 00494 SeeIfUserDrawingOnCanvas(p, touchcode); 00495 } 00496 } else { 00497 //non-touch 00498 } 00499 } 00500 } 00501 00502 #include <stdarg.h> 00503 //Custom override for error() 00504 void error(const char* format, ...) 00505 { 00506 char sprintf_buffer[128]; 00507 00508 va_list arg; 00509 va_start(arg, format); 00510 vsprintf(sprintf_buffer, format, arg); 00511 va_end(arg); 00512 00513 fprintf(stderr, "SW err: %s", sprintf_buffer); 00514 } 00515 00516 // Reset_Handler 00517 // NMI_Handler 00518 // HardFault_Handler 00519 // MemManage_Handler 00520 // BusFault_Handler 00521 // UsageFault_Handler 00522 extern "C" void HardFault_Handler() 00523 { 00524 printf("\r\n\r\nHard Fault!\r\n"); 00525 wait_ms(500); 00526 NVIC_SystemReset(); 00527 } 00528 extern "C" void NMI_Handler() 00529 { 00530 printf("\r\n\r\nNMI Fault!\r\n"); 00531 wait_ms(500); 00532 NVIC_SystemReset(); 00533 } 00534 extern "C" void MemManage_Handler() 00535 { 00536 printf("\r\n\r\nMemManage Fault!\r\n"); 00537 wait_ms(500); 00538 NVIC_SystemReset(); 00539 } 00540 extern "C" void BusFault_Handler() 00541 { 00542 printf("\r\n\r\nBusFault Fault!\r\n"); 00543 wait_ms(500); 00544 NVIC_SystemReset(); 00545 } 00546 extern "C" void UsageFault_Handler() 00547 { 00548 printf("\r\n\r\nUsageFault Fault!\r\n"); 00549 wait_ms(500); 00550 NVIC_SystemReset(); 00551 }
Generated on Sat Jul 16 2022 06:39:53 by 1.7.2