mbed Paint for the RA8875 display with based touch screen.

Dependencies:   menu mbed RA8875

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

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 }