Demo of RA8875 TFT touch display on Freescale FRDM-K64F Forked from David Smart https://developer.mbed.org/users/WiredHome/

Dependencies:   RA8875 menu SDFileSystem mbed

Fork of PUB_RA8875_mPaint by David Smart

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