mbed Paint for the RA8875 display with based touch screen.

Dependencies:   menu mbed RA8875

mPaint

mbed Paint - a demo for the (480x272) RA8875 Display with touchscreen.

Touch Screen

Having had several of the 4.3" WQVGA displays (that use the RA8875), I created the RA8875 driver library (initially derived derived from the work of others). Absent for some time was support for the touch-screen interface. Support first appeared with the contributions of others, and then a major update (due to a recent acquisition of a touch-screen version). This is now much more fully developed and it is part of the standard library.

Demo the Touch Screen

How to demonstrate the touch screen support? mPaint was created for just that purpose.

Screen Shots

Here's a couple of screen shots - you can capture the "canvas" (left) or the composite image (right). As you see, the composite picks up the menu information, however it remains subdued because of the transparency setting.

/media/uploads/WiredHome/mpaint_screen01.png/media/uploads/WiredHome/mpaint_screen02.png

Program Build Info

I'm sometimes a bit skeptical of the reported metrics (perhaps because most of my mbed applications have Ethernet), but here is the reported information from the build of this program.

mPaint Build Infoblinky Build Info
/media/uploads/WiredHome/mpaint_buildinfo.png/media/uploads/WiredHome/blinky_buildinfo.png
RA8875 Graphics library is the primary user.blinky is almost all "startup code" and standard libs

How does mPaint and the graphics library do this in about 1 kB RAM?

The answer is that the display is used as a "write-only" memory, and it has enough RAM hosted in the RA8875 for two full screens (in the WQVGA mode).

mPaint features

  • RGB color selection using touch, with a visible sample.
  • Pen size selection.
    From a limited set.
  • Tool choices.
    Dot, Line, Joined lines.
  • Save your creation.
    Select File | Save..., and it reads the display memory as it creates the BMP file on the local file system.
    This is rather slow (due to both the display read and the local file system).
  • Sorry, no undo.
    If you don't like what "ink" you put down, you can draw over it (much like other paint programs).

Files at this revision

API Documentation at this revision

Comitter:
WiredHome
Date:
Sat Jan 03 15:41:51 2015 +0000
Parent:
1:0fdc10700ed2
Child:
3:3b214426761d
Commit message:
A simple mbed Paint program to demonstrate the RA8875 Touchscreen interface.

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
menu.cpp Show diff for this revision Revisions of this file
menu.h Show diff for this revision Revisions of this file
menu.lib Show annotated file Show diff for this revision Revisions of this file
--- a/main.cpp	Fri Jan 02 23:19:26 2015 +0000
+++ b/main.cpp	Sat Jan 03 15:41:51 2015 +0000
@@ -332,9 +332,9 @@
 
 void ThickLine(point_t origin, point_t p)
 {
-    double angleN = 0;
-    loc_t dy = 0;
-    loc_t dx = 0;
+    double angleN;
+    loc_t dy;
+    loc_t dx;
     point_t s = { 0, 0 };
     point_t e = { 0, 0 };
 
@@ -344,7 +344,7 @@
     dy = p.y - origin.y;
     dx = p.x - origin.x;
     INFO("delta (%+3d,%+3d)", dx,dy);
-    angleN = atan2((double)(p.y-origin.y), (double)(p.x-origin.x));
+    angleN = atan2((double)(dy), (double)(dx));
     if (pensize == 1) {
         lcd.line(origin, p, rgb);
     } else {
--- a/menu.cpp	Fri Jan 02 23:19:26 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,222 +0,0 @@
-
-#include "menu.h"
-
-//#define DEBUG "menu"
-// ...
-// INFO("Stuff to show %d", var); // new-line is automatically appended
-//
-#if (defined(DEBUG) && !defined(TARGET_LPC11U24))
-#define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
-#define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
-#define ERR(x, ...)  std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
-#else
-#define INFO(x, ...)
-#define WARN(x, ...)
-#define ERR(x, ...)
-#define HexDump(a, b, c)
-#endif
-
-Menu::~Menu()
-{
-}
-
-Menu::Menu(RA8875 & _lcd, menu_item_t * _menu, color_t fg, color_t bg, color_t hl) 
-    : lcd(_lcd), pTopMenu(_menu), pExpanded(0), isShowing(false), 
-    menuForeground(fg), menuBackground(bg), menuHighlight(hl)
-{
-}
-
-void Menu::init()
-{
-    lcd.SetLayerMode(RA8875::TransparentMode);
-    lcd.SetLayerTransparency(0, 7);
-}
-
-void Menu::SetColors(color_t fg, color_t bg)
-{
-    menuForeground = fg;
-    menuBackground = bg;
-}
-
-bool Menu::_isTouched(menu_item_t * pMenu, rect_t r, point_t p, menu_item_t ** menuTouched)
-{
-    while (pMenu->menuText) {
-        r.p2.x += lcd.fontwidth() * (strlen(pMenu->menuText) + strlen("  "));
-        INFO("Is (%3d,%3d) in (%3d,%3d)-(%3d,%3d) %s [%s]", 
-            p.x, p.y, r.p1.x, r.p1.y, r.p2.x, r.p2.y, pMenu->menuText,
-            pExpanded ? pExpanded->child->menuText : "");
-        if (lcd.Intersect(r, p)) {
-            *menuTouched = pMenu;
-            return true;
-        }
-        if (!isShowing)   // Activating this traps the menu activation to the first entry only.
-            break;        // Disabling this permits anything on the top-line
-        if (isShowing && pMenu->child && pExpanded == pMenu) {
-            r.p1.x += lcd.fontwidth();
-            r.p1.y += lcd.fontheight();
-            r.p2.x = r.p1.x;
-            r.p2.y = r.p1.y + lcd.fontheight();
-            if (_isTouched(pMenu->child, r, p, menuTouched)) {
-                return true;
-            }
-        }
-        r.p1.x = r.p2.x;
-        pMenu++;
-    }
-    return false;
-}
-
-bool Menu::HandledTouch(point_t p, TouchCode_t touchcode)
-{
-    rect_t r;
-    menu_item_t * pTouchedMenu = NULL;
-    bool handled = false;
-    
-    r.p1.x = r.p1.y = r.p2.x = 0;
-    r.p2.y = lcd.fontheight();
-    
-    if (_isTouched(pTopMenu, r, p, &pTouchedMenu)) {
-        INFO("Touched %s.\r\n", pTouchedMenu->menuText);
-        if (pTouchedMenu == pTopMenu && !isShowing && touchcode == touch) {
-            INFO("Show menu...\r\n");
-            Show();
-            INFO("  show done.\r\n");
-        } else {
-            post_fnc_action_t action = no_action;
-            
-            switch (touchcode) {
-                case touch:
-                    if (pTouchedMenu->fncPress) {
-                        action = pTouchedMenu->fncPress(pTouchedMenu->param);
-                    }
-                    if (pTouchedMenu->child) {
-                        INFO("  Expand %s.\r\n", pTouchedMenu->menuText);
-                        Expand(pTouchedMenu);
-                        INFO("  done.\r\n");
-                    }
-                    break;
-                case held:
-                    if (pTouchedMenu->fncHeld) {
-                        action = pTouchedMenu->fncHeld(pTouchedMenu->param);
-                    }
-                    break;
-                case release:
-                    if (pTouchedMenu->fncRelease) {
-                        action = pTouchedMenu->fncRelease(pTouchedMenu->param);
-                    }
-                    break;
-                default:
-                    break;
-            }
-            if (action == close_menu) {
-                Hide();
-            }
-        }
-        handled = true;
-    }
-    return handled;
-}
-
-
-bool Menu::_GetMenuRect(menu_item_t * pMenu, menu_item_t * needle, rect_t * pRect)
-{
-    rect_t r;
-    
-    if (needle->menuText == NULL)
-        return false;
-    r.p1.x = r.p1.y = r.p2.x = 0;
-    r.p2.y = lcd.fontheight();
-    while (pMenu->menuText) {
-        r.p2.x += lcd.fontwidth() * (strlen(pMenu->menuText) + strlen("  "));
-        if (pMenu == needle) {
-            *pRect = r;
-            return true;
-        }
-        r.p1.x = r.p2.x;
-        pMenu++;
-    }
-    return false;
-}
-
-void Menu::_Rect(rect_t r, color_t c, fill_t fill)
-{
-    r.p2.x--;
-    r.p2.y--;
-    lcd.rect(r, c, fill);
-}
-
-
-void Menu::Expand(menu_item_t * thisMenu)
-{
-    rect_t r;
-    bool same = (pExpanded == thisMenu) ? true : false;
-    
-    if (pExpanded) { // need to hide this one first
-        INFO("  Hiding children of %s.", pExpanded->menuText);
-        _GetMenuRect(pTopMenu, pExpanded, &r);
-        _Rect(r, menuForeground);
-        r.p1.x += lcd.fontwidth();
-        r.p1.y += lcd.fontheight();
-        r.p2.x = r.p1.x;
-        r.p2.y = r.p1.y + lcd.fontheight();
-        _ShowMenu_Helper(pExpanded->child, r, false);
-        pExpanded = NULL;
-    }
-    if (!same && _GetMenuRect(pTopMenu, thisMenu, &r)) {
-        INFO("  Expanding to children of %s.", thisMenu->menuText);
-        _Rect(r, menuHighlight);
-        // index in a little, then down a row
-        r.p1.x += lcd.fontwidth();
-        r.p1.y += lcd.fontheight();
-        r.p2.x = r.p1.x;
-        r.p2.y = r.p1.y + lcd.fontheight();
-        _ShowMenu_Helper(thisMenu->child, r);
-        pExpanded = thisMenu;
-    }
-}
-
-void Menu::Show()
-{
-    rect_t r;
-    INFO("Show()");
-    lcd.SelectDrawingLayer(MENUS);
-    lcd.SetLayerTransparency(7, 0);
-    //lcd.cls();
-    lcd.SetTextCursor(0,0);
-    r.p1.x = r.p1.y = r.p2.x = 0;
-    r.p2.y = lcd.fontheight();
-    menu_item_t * pMenu = pTopMenu;
-    _ShowMenu_Helper(pMenu, r);
-    isShowing = true;
-}
-
-void Menu::_ShowMenu_Helper(menu_item_t * pMenu, rect_t r, bool show)
-{
-    while (pMenu->menuText) {
-        lcd.SetTextCursor(r.p1.x, r.p1.y);
-        r.p2.x += lcd.fontwidth() * (strlen(pMenu->menuText) + strlen("  "));
-        if (show) {
-            INFO("(%3d,%3d)-(%3d,%3d) %s", r.p1.x, r.p1.y, r.p2.x, r.p2.y, pMenu->menuText);
-            lcd.foreground(menuForeground);
-            lcd.printf(" %s ", pMenu->menuText);
-            _Rect(r, menuForeground);
-        } else {
-            INFO("HIDE (%3d,%3d)-(%3d,%3d) %s", r.p1.x, r.p1.y, r.p2.x, r.p2.y, pMenu->menuText);
-            _Rect(r, menuBackground, FILL);
-        }
-        r.p1.x = r.p2.x;
-        pMenu++;
-    }
-    isShowing = true;
-}
-
-void Menu::Hide()
-{
-    INFO("Hide()");
-    if (pExpanded)
-        Expand(pExpanded); // hides this menu
-    lcd.SelectDrawingLayer(CANVAS);
-    isShowing = false;
-    lcd.SetLayerTransparency(0, 7);
-}
-
--- a/menu.h	Fri Jan 02 23:19:26 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-
-#ifndef MENU_H
-#define MENU_H
-
-#include "RA8875.h"
-
-#define CANVAS  0
-#define MENUS   1
-
-class Menu
-{
-public:
-    typedef enum 
-    {
-        no_action,
-        close_menu,
-    } post_fnc_action_t;
-    
-    typedef struct menu_item_t
-    {
-        char * menuText;
-        post_fnc_action_t (* fncPress)(uint32_t);
-        post_fnc_action_t (* fncHeld)(uint32_t);
-        post_fnc_action_t (* fncRelease)(uint32_t);
-        uint32_t param;
-        menu_item_t * child;
-    } menu_item_t;
-
-    Menu(RA8875 & lcd, menu_item_t * menu, color_t fg = BrightBlue, color_t bg = Black, color_t hl = Red);
-    ~Menu();
-    void init(void);
-    void Expand(menu_item_t * menu);
-    bool HandledTouch(point_t p, TouchCode_t touchcode);
-    void Show();
-    void Hide();
-    bool isVisible() { return isShowing; }
-    void SetColors(color_t fg, color_t bg);
-    
-private:
-    bool _isTouched(menu_item_t * pTraverse, rect_t r, point_t p, menu_item_t ** menuTouched);
-    bool _GetMenuRect(menu_item_t * pMenu, menu_item_t * needle, rect_t * pRect);
-    void _ShowMenu_Helper(menu_item_t * pMenu, rect_t r, bool show = true);
-    void _Rect(rect_t r, color_t c, fill_t fill = NOFILL);
-    RA8875 & lcd;
-    menu_item_t * pTopMenu;
-    menu_item_t * pExpanded;    // points to an expanded menu
-    bool isShowing;
-    color_t menuForeground;
-    color_t menuBackground;
-    color_t menuHighlight;
-};
-
-#endif // MENU_H
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/menu.lib	Sat Jan 03 15:41:51 2015 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/WiredHome/code/menu/#905736afd672