Example using the support package for LPC4088 DisplayModule

Dependencies:   DMBasicGUI DMSupport

Example using a lot of the features in the software package for the LPC4088 Display Module.

This project can be selected as a template when creating a new project based on the LPC4088 Display Module.

Information

This project works on the 4.3" display modules.

Some of the apps works on the 5" display modules. The ImageViewer and Slideshow app will show the images distorted as it does not take the resolution into consideration.

Information

The USB Status app is disabled. The Image viewer looks for images in the root of SD cards, USB memory sticks or the file system on the QSPI flash. The Slideshow app expects to find a slideshow script in /mci/elec14/ea_logo.txt.

This is what it looks like on the 4.3" display:

/media/uploads/embeddedartists/everything_cap_000.png /media/uploads/embeddedartists/everything_cap_001.png /media/uploads/embeddedartists/everything_cap_003.png /media/uploads/embeddedartists/everything_cap_004.png /media/uploads/embeddedartists/everything_cap_006.png /media/uploads/embeddedartists/everything_cap_008.png

Committer:
embeddedartists
Date:
Tue Feb 17 10:46:06 2015 +0100
Revision:
24:768f5958c308
Parent:
22:7e59255933b5
Child:
28:be5b06633d98
- Modified AppRTCSettings to use current time when initializing
- Added AppDraw to show off multitouch (works with single touch as well)
- Replaced wait with Thread::wait in main()
- Moved the ok/cancel button data into DMBasicGUI, overridable with
DM_BOARD_USE_BUILTIN_IMAGES
- Updated the DM_Support library (see version history there for changes)
- Updated the DM_BasicGUI library (see version history there for changes)
- Added texts to the icons in the launcher

Who changed what in which revision?

UserRevisionLine numberNew contents of line
embeddedartists 13:57e65aba9802 1 /*
embeddedartists 13:57e65aba9802 2 * Copyright 2014 Embedded Artists AB
embeddedartists 13:57e65aba9802 3 *
embeddedartists 13:57e65aba9802 4 * Licensed under the Apache License, Version 2.0 (the "License");
embeddedartists 13:57e65aba9802 5 * you may not use this file except in compliance with the License.
embeddedartists 13:57e65aba9802 6 * You may obtain a copy of the License at
embeddedartists 13:57e65aba9802 7 *
embeddedartists 13:57e65aba9802 8 * http://www.apache.org/licenses/LICENSE-2.0
embeddedartists 13:57e65aba9802 9 *
embeddedartists 13:57e65aba9802 10 * Unless required by applicable law or agreed to in writing, software
embeddedartists 13:57e65aba9802 11 * distributed under the License is distributed on an "AS IS" BASIS,
embeddedartists 13:57e65aba9802 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
embeddedartists 13:57e65aba9802 13 * See the License for the specific language governing permissions and
embeddedartists 13:57e65aba9802 14 * limitations under the License.
embeddedartists 13:57e65aba9802 15 */
embeddedartists 13:57e65aba9802 16
embeddedartists 13:57e65aba9802 17
embeddedartists 13:57e65aba9802 18 #include "mbed.h"
embeddedartists 13:57e65aba9802 19 #include "AppImageViewer.h"
embeddedartists 13:57e65aba9802 20 #include "lpc_swim_font.h"
embeddedartists 13:57e65aba9802 21 #include "lpc_swim_image.h"
embeddedartists 13:57e65aba9802 22 #include "Image.h"
embeddedartists 13:57e65aba9802 23 #include "image_data.h"
embeddedartists 13:57e65aba9802 24
embeddedartists 13:57e65aba9802 25 /******************************************************************************
embeddedartists 13:57e65aba9802 26 * Defines and typedefs
embeddedartists 13:57e65aba9802 27 *****************************************************************************/
embeddedartists 13:57e65aba9802 28
embeddedartists 13:57e65aba9802 29 #define BOX_SIDE 192 //256
embeddedartists 13:57e65aba9802 30
embeddedartists 13:57e65aba9802 31 #define BTN_WIDTH 40
embeddedartists 13:57e65aba9802 32 #define BTN_HEIGHT 40
embeddedartists 13:57e65aba9802 33 #define BTN_OFF 20
embeddedartists 13:57e65aba9802 34
embeddedartists 13:57e65aba9802 35 /******************************************************************************
embeddedartists 13:57e65aba9802 36 * Global variables
embeddedartists 13:57e65aba9802 37 *****************************************************************************/
embeddedartists 13:57e65aba9802 38
embeddedartists 13:57e65aba9802 39 /******************************************************************************
embeddedartists 13:57e65aba9802 40 * Private functions
embeddedartists 13:57e65aba9802 41 *****************************************************************************/
embeddedartists 13:57e65aba9802 42
embeddedartists 13:57e65aba9802 43 static void buttonClicked(uint32_t x)
embeddedartists 13:57e65aba9802 44 {
embeddedartists 13:57e65aba9802 45 bool* done = (bool*)x;
embeddedartists 13:57e65aba9802 46 *done = true;
embeddedartists 13:57e65aba9802 47 }
embeddedartists 13:57e65aba9802 48
embeddedartists 13:57e65aba9802 49 void AppImageViewer::draw()
embeddedartists 13:57e65aba9802 50 {
embeddedartists 13:57e65aba9802 51 // Prepare fullscreen
embeddedartists 13:57e65aba9802 52 swim_window_open(_win,
embeddedartists 13:57e65aba9802 53 _disp->width(), _disp->height(), // full size
embeddedartists 13:57e65aba9802 54 (COLOR_T*)_fb1,
embeddedartists 13:57e65aba9802 55 0,0,_disp->width()-1, _disp->height()-1, // window position and size
embeddedartists 13:57e65aba9802 56 0, // border
embeddedartists 13:57e65aba9802 57 BLACK, BLACK, BLACK); // colors: pen, backgr, forgr
embeddedartists 13:57e65aba9802 58
embeddedartists 13:57e65aba9802 59 _btn = new ImageButton(_win->fb, _win->xpmax - BTN_OFF - BTN_WIDTH, _win->ypmax - BTN_OFF - BTN_HEIGHT, BTN_WIDTH, BTN_HEIGHT);
embeddedartists 13:57e65aba9802 60 _btn->loadImages(img_ok, img_size_ok);
embeddedartists 13:57e65aba9802 61 }
embeddedartists 13:57e65aba9802 62
embeddedartists 13:57e65aba9802 63 void AppImageViewer::load(const char* file)
embeddedartists 13:57e65aba9802 64 {
embeddedartists 13:57e65aba9802 65 Image::ImageData_t pre = {0};
embeddedartists 13:57e65aba9802 66
embeddedartists 13:57e65aba9802 67 int res = Image::decode(file, Image::RES_16BIT, &pre);
embeddedartists 13:57e65aba9802 68 if (res == 0) {
embeddedartists 13:57e65aba9802 69 DMBoard::instance().logger()->printf("[ImageLoader] Preparing %s\n", file);
embeddedartists 13:57e65aba9802 70 Image::ImageData_t* data = _mailbox.alloc(osWaitForever);
embeddedartists 13:57e65aba9802 71 if (data != NULL) {
embeddedartists 13:57e65aba9802 72 *data = pre;
embeddedartists 13:57e65aba9802 73 _mailbox.put(data);
embeddedartists 13:57e65aba9802 74 } else {
embeddedartists 13:57e65aba9802 75 DMBoard::instance().logger()->printf("[ImageLoader] Failed to get memory to prepare %s\n", file);
embeddedartists 13:57e65aba9802 76 }
embeddedartists 13:57e65aba9802 77 }
embeddedartists 13:57e65aba9802 78 }
embeddedartists 13:57e65aba9802 79
embeddedartists 22:7e59255933b5 80 static bool recursiveProcessFS(char* buff, const char* name, unsigned int maxLen, AppImageViewer* app, int depth, int maxDepth)
embeddedartists 13:57e65aba9802 81 {
embeddedartists 13:57e65aba9802 82 if (depth > maxDepth) {
embeddedartists 13:57e65aba9802 83 return true;
embeddedartists 13:57e65aba9802 84 }
embeddedartists 13:57e65aba9802 85 uint32_t len = strlen(buff);
embeddedartists 13:57e65aba9802 86 if (len > 0) {
embeddedartists 13:57e65aba9802 87 if (buff[len - 1] != '/') {
embeddedartists 13:57e65aba9802 88 buff[len++] = '/';
embeddedartists 13:57e65aba9802 89 buff[len] = '\0';
embeddedartists 13:57e65aba9802 90 }
embeddedartists 13:57e65aba9802 91 }
embeddedartists 13:57e65aba9802 92 if ((strlen(name) + len) >= maxLen) {
embeddedartists 13:57e65aba9802 93 // avoid memory overwrite due to too long file path
embeddedartists 13:57e65aba9802 94 return true;
embeddedartists 13:57e65aba9802 95 }
embeddedartists 13:57e65aba9802 96 strcat(buff, name);
embeddedartists 13:57e65aba9802 97 len += strlen(name);
embeddedartists 13:57e65aba9802 98
embeddedartists 13:57e65aba9802 99 DIR *d = opendir(buff);
embeddedartists 13:57e65aba9802 100 bool result = true; // success
embeddedartists 13:57e65aba9802 101 if (d != NULL) {
embeddedartists 13:57e65aba9802 102 struct dirent *p;
embeddedartists 13:57e65aba9802 103 while (result && ((p = readdir(d)) != NULL)) {
embeddedartists 13:57e65aba9802 104 result = recursiveProcessFS(buff, p->d_name, maxLen, app, depth+1, maxDepth);
embeddedartists 13:57e65aba9802 105 buff[len] = '\0';
embeddedartists 13:57e65aba9802 106 }
embeddedartists 13:57e65aba9802 107 closedir(d);
embeddedartists 13:57e65aba9802 108 } else {
embeddedartists 13:57e65aba9802 109 // a file
embeddedartists 13:57e65aba9802 110 if (len > 3) {
embeddedartists 13:57e65aba9802 111 if ((strncasecmp(buff+len-4, ".bmp", 4)==0) ||
embeddedartists 13:57e65aba9802 112 (strncasecmp(buff+len-4, ".png", 4)==0) ||
embeddedartists 13:57e65aba9802 113 (strncasecmp(buff+len-4, ".raw", 4)==0)) {
embeddedartists 13:57e65aba9802 114 DMBoard::instance().logger()->printf("[ImageLoader] found %s\n", buff);
embeddedartists 13:57e65aba9802 115 app->load(buff);
embeddedartists 13:57e65aba9802 116 }
embeddedartists 13:57e65aba9802 117 }
embeddedartists 13:57e65aba9802 118 }
embeddedartists 13:57e65aba9802 119 return result;
embeddedartists 13:57e65aba9802 120 }
embeddedartists 13:57e65aba9802 121
embeddedartists 13:57e65aba9802 122 static void loaderTask(void const* args)
embeddedartists 13:57e65aba9802 123 {
embeddedartists 13:57e65aba9802 124 char* buff = (char*)malloc(512);
embeddedartists 13:57e65aba9802 125 if (buff != NULL)
embeddedartists 13:57e65aba9802 126 {
embeddedartists 13:57e65aba9802 127 DMBoard::instance().logger()->printf("Recursive list of file and folders in /mci/\n");
embeddedartists 13:57e65aba9802 128 buff[0] = '\0';
embeddedartists 13:57e65aba9802 129 recursiveProcessFS(buff, "/mci/", 512, (AppImageViewer*)args, 0, 2);
embeddedartists 13:57e65aba9802 130 DMBoard::instance().logger()->printf("Recursive list of file and folders in /usb/\n");
embeddedartists 13:57e65aba9802 131 buff[0] = '\0';
embeddedartists 13:57e65aba9802 132 recursiveProcessFS(buff, "/usb/", 512, (AppImageViewer*)args, 0, 2);
embeddedartists 13:57e65aba9802 133 DMBoard::instance().logger()->printf("Recursive list of file and folders in /qspi/\n");
embeddedartists 13:57e65aba9802 134 buff[0] = '\0';
embeddedartists 13:57e65aba9802 135 recursiveProcessFS(buff, "/qspi/", 512, (AppImageViewer*)args, 0, 2);
embeddedartists 13:57e65aba9802 136 free(buff);
embeddedartists 13:57e65aba9802 137 }
embeddedartists 13:57e65aba9802 138 DMBoard::instance().logger()->printf("loaderTask done\n");
embeddedartists 13:57e65aba9802 139 }
embeddedartists 13:57e65aba9802 140
embeddedartists 13:57e65aba9802 141 /******************************************************************************
embeddedartists 13:57e65aba9802 142 * Public functions
embeddedartists 13:57e65aba9802 143 *****************************************************************************/
embeddedartists 13:57e65aba9802 144
embeddedartists 13:57e65aba9802 145 AppImageViewer::AppImageViewer() : _disp(NULL), _win(NULL), _fb1(NULL), _fb2(NULL), _btn(NULL), _active(0)
embeddedartists 13:57e65aba9802 146 {
embeddedartists 13:57e65aba9802 147 }
embeddedartists 13:57e65aba9802 148
embeddedartists 13:57e65aba9802 149 AppImageViewer::~AppImageViewer()
embeddedartists 13:57e65aba9802 150 {
embeddedartists 13:57e65aba9802 151 teardown();
embeddedartists 13:57e65aba9802 152 }
embeddedartists 13:57e65aba9802 153
embeddedartists 13:57e65aba9802 154 bool AppImageViewer::setup()
embeddedartists 13:57e65aba9802 155 {
embeddedartists 13:57e65aba9802 156 _disp = DMBoard::instance().display();
embeddedartists 13:57e65aba9802 157 _win = (SWIM_WINDOW_T*)malloc(sizeof(SWIM_WINDOW_T));
embeddedartists 13:57e65aba9802 158 _fb1 = _disp->allocateFramebuffer();
embeddedartists 13:57e65aba9802 159 _fb2 = _disp->allocateFramebuffer();
embeddedartists 13:57e65aba9802 160
embeddedartists 13:57e65aba9802 161 return (_win != NULL && _fb1 != NULL && _fb2 != NULL);
embeddedartists 13:57e65aba9802 162 }
embeddedartists 13:57e65aba9802 163
embeddedartists 13:57e65aba9802 164 void AppImageViewer::runToCompletion()
embeddedartists 13:57e65aba9802 165 {
embeddedartists 13:57e65aba9802 166 // Alternative 1: use the calling thread's context to run in
embeddedartists 13:57e65aba9802 167 bool done = false;
embeddedartists 13:57e65aba9802 168 draw();
embeddedartists 13:57e65aba9802 169 _btn->setAction(buttonClicked, (uint32_t)&done);
embeddedartists 13:57e65aba9802 170 void* oldFB = _disp->swapFramebuffer(_fb1);
embeddedartists 13:57e65aba9802 171
embeddedartists 13:57e65aba9802 172 _active = 1;
embeddedartists 13:57e65aba9802 173
embeddedartists 13:57e65aba9802 174 Thread* tLoader = new Thread(loaderTask, this, osPriorityNormal, 8192);
embeddedartists 13:57e65aba9802 175
embeddedartists 13:57e65aba9802 176 bool first = true;
embeddedartists 13:57e65aba9802 177 Timer t;
embeddedartists 13:57e65aba9802 178 while(!done) {
embeddedartists 13:57e65aba9802 179 osEvent evt = _mailbox.get(1000);
embeddedartists 13:57e65aba9802 180 if (evt.status == osEventMail) {
embeddedartists 13:57e65aba9802 181 COLOR_T* fb;
embeddedartists 13:57e65aba9802 182 if (_active == 1) {
embeddedartists 13:57e65aba9802 183 // render on the second frame buffer
embeddedartists 13:57e65aba9802 184 fb = (COLOR_T*)_fb2;
embeddedartists 13:57e65aba9802 185 } else {
embeddedartists 13:57e65aba9802 186 // render on the first frame buffer
embeddedartists 13:57e65aba9802 187 fb = (COLOR_T*)_fb1;
embeddedartists 13:57e65aba9802 188 }
embeddedartists 13:57e65aba9802 189 _win->fb = fb;
embeddedartists 13:57e65aba9802 190 Image::ImageData_t* data = (Image::ImageData_t*)evt.value.p;
embeddedartists 24:768f5958c308 191 swim_put_image_xy(_win, (COLOR_T*)data->pixels, data->width, data->height, _disp->width()-data->width, _disp->height()-data->height);
embeddedartists 18:715f542538b3 192 free(data->pointerToFree);
embeddedartists 13:57e65aba9802 193 _mailbox.free(data);
embeddedartists 13:57e65aba9802 194 if (first) {
embeddedartists 13:57e65aba9802 195 first = false;
embeddedartists 13:57e65aba9802 196 t.start();
embeddedartists 13:57e65aba9802 197 } else {
embeddedartists 13:57e65aba9802 198 while (t.read_ms() < 2000) {
embeddedartists 13:57e65aba9802 199 Thread::wait(100);
embeddedartists 13:57e65aba9802 200 }
embeddedartists 13:57e65aba9802 201 }
embeddedartists 13:57e65aba9802 202 _disp->setFramebuffer(fb);
embeddedartists 13:57e65aba9802 203 _active = (_active == 1 ? 2 : 1);
embeddedartists 13:57e65aba9802 204 t.reset();
embeddedartists 13:57e65aba9802 205 } else if (tLoader->get_state() == Thread::Inactive) {
embeddedartists 13:57e65aba9802 206 // No more images in the queue and the loader thread
embeddedartists 13:57e65aba9802 207 // has completed its search
embeddedartists 13:57e65aba9802 208 break;
embeddedartists 13:57e65aba9802 209 }
embeddedartists 13:57e65aba9802 210 }
embeddedartists 13:57e65aba9802 211
embeddedartists 13:57e65aba9802 212 delete tLoader;
embeddedartists 13:57e65aba9802 213
embeddedartists 13:57e65aba9802 214 // The button must be drawn on the current framebuffer
embeddedartists 13:57e65aba9802 215 _btn->draw(_win->fb);
embeddedartists 13:57e65aba9802 216
embeddedartists 16:77f4f42eb6a7 217 // Wait for touches, but the AppLauncher is already listening
embeddedartists 16:77f4f42eb6a7 218 // for new touch event and sends a signal to its thread which
embeddedartists 16:77f4f42eb6a7 219 // is the same as runs this function so it is enough to wait
embeddedartists 16:77f4f42eb6a7 220 // for that signal.
embeddedartists 13:57e65aba9802 221 TouchPanel* touch = DMBoard::instance().touchPanel();
embeddedartists 16:77f4f42eb6a7 222 touch_coordinate_t coord;
embeddedartists 13:57e65aba9802 223 while(!done) {
embeddedartists 16:77f4f42eb6a7 224 Thread::signal_wait(0x1);
embeddedartists 13:57e65aba9802 225 if (touch->read(coord) == TouchPanel::TouchError_Ok) {
embeddedartists 13:57e65aba9802 226 if (_btn->handle(coord.x, coord.y, coord.z > 0)) {
embeddedartists 13:57e65aba9802 227 _btn->draw();
embeddedartists 13:57e65aba9802 228 }
embeddedartists 13:57e65aba9802 229 }
embeddedartists 13:57e65aba9802 230 }
embeddedartists 13:57e65aba9802 231
embeddedartists 13:57e65aba9802 232 // User has clicked the button, restore the original FB
embeddedartists 13:57e65aba9802 233 _disp->swapFramebuffer(oldFB);
embeddedartists 13:57e65aba9802 234 swim_window_close(_win);
embeddedartists 13:57e65aba9802 235 }
embeddedartists 13:57e65aba9802 236
embeddedartists 13:57e65aba9802 237 bool AppImageViewer::teardown()
embeddedartists 13:57e65aba9802 238 {
embeddedartists 13:57e65aba9802 239 if (_win != NULL) {
embeddedartists 13:57e65aba9802 240 free(_win);
embeddedartists 13:57e65aba9802 241 _win = NULL;
embeddedartists 13:57e65aba9802 242 }
embeddedartists 13:57e65aba9802 243 if (_fb1 != NULL) {
embeddedartists 13:57e65aba9802 244 free(_fb1);
embeddedartists 13:57e65aba9802 245 _fb1 = NULL;
embeddedartists 13:57e65aba9802 246 }
embeddedartists 13:57e65aba9802 247 if (_fb2 != NULL) {
embeddedartists 13:57e65aba9802 248 free(_fb2);
embeddedartists 13:57e65aba9802 249 _fb2 = NULL;
embeddedartists 13:57e65aba9802 250 }
embeddedartists 13:57e65aba9802 251 if (_btn != NULL) {
embeddedartists 13:57e65aba9802 252 delete _btn;
embeddedartists 13:57e65aba9802 253 _btn = NULL;
embeddedartists 13:57e65aba9802 254 }
embeddedartists 13:57e65aba9802 255 return true;
embeddedartists 13:57e65aba9802 256 }
embeddedartists 13:57e65aba9802 257
embeddedartists 13:57e65aba9802 258