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:
alindvall
Date:
Tue Apr 28 11:49:03 2015 +0000
Revision:
29:be8b784873f5
Parent:
28:be5b06633d98
Child:
30:e1cded731965
Updated to latest version of the DMSupport library

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 28:be5b06633d98 61 // Copy everything onto the back buffer
embeddedartists 28:be5b06633d98 62 memcpy(_fb2, _fb1, _disp->fbSize());
embeddedartists 13:57e65aba9802 63 }
embeddedartists 13:57e65aba9802 64
embeddedartists 13:57e65aba9802 65 void AppImageViewer::load(const char* file)
embeddedartists 13:57e65aba9802 66 {
embeddedartists 13:57e65aba9802 67 Image::ImageData_t pre = {0};
embeddedartists 13:57e65aba9802 68
embeddedartists 13:57e65aba9802 69 int res = Image::decode(file, Image::RES_16BIT, &pre);
embeddedartists 13:57e65aba9802 70 if (res == 0) {
embeddedartists 13:57e65aba9802 71 DMBoard::instance().logger()->printf("[ImageLoader] Preparing %s\n", file);
embeddedartists 13:57e65aba9802 72 Image::ImageData_t* data = _mailbox.alloc(osWaitForever);
embeddedartists 13:57e65aba9802 73 if (data != NULL) {
embeddedartists 13:57e65aba9802 74 *data = pre;
embeddedartists 13:57e65aba9802 75 _mailbox.put(data);
embeddedartists 13:57e65aba9802 76 } else {
embeddedartists 13:57e65aba9802 77 DMBoard::instance().logger()->printf("[ImageLoader] Failed to get memory to prepare %s\n", file);
embeddedartists 13:57e65aba9802 78 }
embeddedartists 13:57e65aba9802 79 }
embeddedartists 13:57e65aba9802 80 }
embeddedartists 13:57e65aba9802 81
embeddedartists 22:7e59255933b5 82 static bool recursiveProcessFS(char* buff, const char* name, unsigned int maxLen, AppImageViewer* app, int depth, int maxDepth)
embeddedartists 13:57e65aba9802 83 {
embeddedartists 13:57e65aba9802 84 if (depth > maxDepth) {
embeddedartists 13:57e65aba9802 85 return true;
embeddedartists 13:57e65aba9802 86 }
embeddedartists 13:57e65aba9802 87 uint32_t len = strlen(buff);
embeddedartists 13:57e65aba9802 88 if (len > 0) {
embeddedartists 13:57e65aba9802 89 if (buff[len - 1] != '/') {
embeddedartists 13:57e65aba9802 90 buff[len++] = '/';
embeddedartists 13:57e65aba9802 91 buff[len] = '\0';
embeddedartists 13:57e65aba9802 92 }
embeddedartists 13:57e65aba9802 93 }
embeddedartists 13:57e65aba9802 94 if ((strlen(name) + len) >= maxLen) {
embeddedartists 13:57e65aba9802 95 // avoid memory overwrite due to too long file path
embeddedartists 13:57e65aba9802 96 return true;
embeddedartists 13:57e65aba9802 97 }
embeddedartists 13:57e65aba9802 98 strcat(buff, name);
embeddedartists 13:57e65aba9802 99 len += strlen(name);
embeddedartists 13:57e65aba9802 100
embeddedartists 13:57e65aba9802 101 DIR *d = opendir(buff);
embeddedartists 13:57e65aba9802 102 bool result = true; // success
embeddedartists 13:57e65aba9802 103 if (d != NULL) {
embeddedartists 13:57e65aba9802 104 struct dirent *p;
embeddedartists 13:57e65aba9802 105 while (result && ((p = readdir(d)) != NULL)) {
embeddedartists 13:57e65aba9802 106 result = recursiveProcessFS(buff, p->d_name, maxLen, app, depth+1, maxDepth);
embeddedartists 13:57e65aba9802 107 buff[len] = '\0';
embeddedartists 13:57e65aba9802 108 }
embeddedartists 13:57e65aba9802 109 closedir(d);
embeddedartists 13:57e65aba9802 110 } else {
embeddedartists 13:57e65aba9802 111 // a file
embeddedartists 13:57e65aba9802 112 if (len > 3) {
embeddedartists 13:57e65aba9802 113 if ((strncasecmp(buff+len-4, ".bmp", 4)==0) ||
embeddedartists 13:57e65aba9802 114 (strncasecmp(buff+len-4, ".png", 4)==0) ||
embeddedartists 13:57e65aba9802 115 (strncasecmp(buff+len-4, ".raw", 4)==0)) {
embeddedartists 13:57e65aba9802 116 DMBoard::instance().logger()->printf("[ImageLoader] found %s\n", buff);
embeddedartists 13:57e65aba9802 117 app->load(buff);
embeddedartists 13:57e65aba9802 118 }
embeddedartists 13:57e65aba9802 119 }
embeddedartists 13:57e65aba9802 120 }
embeddedartists 13:57e65aba9802 121 return result;
embeddedartists 13:57e65aba9802 122 }
embeddedartists 13:57e65aba9802 123
embeddedartists 13:57e65aba9802 124 static void loaderTask(void const* args)
embeddedartists 13:57e65aba9802 125 {
embeddedartists 13:57e65aba9802 126 char* buff = (char*)malloc(512);
embeddedartists 13:57e65aba9802 127 if (buff != NULL)
embeddedartists 13:57e65aba9802 128 {
embeddedartists 13:57e65aba9802 129 DMBoard::instance().logger()->printf("Recursive list of file and folders in /mci/\n");
embeddedartists 13:57e65aba9802 130 buff[0] = '\0';
embeddedartists 13:57e65aba9802 131 recursiveProcessFS(buff, "/mci/", 512, (AppImageViewer*)args, 0, 2);
embeddedartists 13:57e65aba9802 132 DMBoard::instance().logger()->printf("Recursive list of file and folders in /usb/\n");
embeddedartists 13:57e65aba9802 133 buff[0] = '\0';
embeddedartists 13:57e65aba9802 134 recursiveProcessFS(buff, "/usb/", 512, (AppImageViewer*)args, 0, 2);
embeddedartists 13:57e65aba9802 135 DMBoard::instance().logger()->printf("Recursive list of file and folders in /qspi/\n");
embeddedartists 13:57e65aba9802 136 buff[0] = '\0';
embeddedartists 13:57e65aba9802 137 recursiveProcessFS(buff, "/qspi/", 512, (AppImageViewer*)args, 0, 2);
embeddedartists 13:57e65aba9802 138 free(buff);
embeddedartists 13:57e65aba9802 139 }
embeddedartists 13:57e65aba9802 140 DMBoard::instance().logger()->printf("loaderTask done\n");
embeddedartists 13:57e65aba9802 141 }
embeddedartists 13:57e65aba9802 142
embeddedartists 13:57e65aba9802 143 /******************************************************************************
embeddedartists 13:57e65aba9802 144 * Public functions
embeddedartists 13:57e65aba9802 145 *****************************************************************************/
embeddedartists 13:57e65aba9802 146
embeddedartists 13:57e65aba9802 147 AppImageViewer::AppImageViewer() : _disp(NULL), _win(NULL), _fb1(NULL), _fb2(NULL), _btn(NULL), _active(0)
embeddedartists 13:57e65aba9802 148 {
embeddedartists 13:57e65aba9802 149 }
embeddedartists 13:57e65aba9802 150
embeddedartists 13:57e65aba9802 151 AppImageViewer::~AppImageViewer()
embeddedartists 13:57e65aba9802 152 {
embeddedartists 13:57e65aba9802 153 teardown();
embeddedartists 13:57e65aba9802 154 }
embeddedartists 13:57e65aba9802 155
embeddedartists 13:57e65aba9802 156 bool AppImageViewer::setup()
embeddedartists 13:57e65aba9802 157 {
embeddedartists 13:57e65aba9802 158 _disp = DMBoard::instance().display();
embeddedartists 13:57e65aba9802 159 _win = (SWIM_WINDOW_T*)malloc(sizeof(SWIM_WINDOW_T));
embeddedartists 13:57e65aba9802 160 _fb1 = _disp->allocateFramebuffer();
embeddedartists 13:57e65aba9802 161 _fb2 = _disp->allocateFramebuffer();
embeddedartists 13:57e65aba9802 162
embeddedartists 13:57e65aba9802 163 return (_win != NULL && _fb1 != NULL && _fb2 != NULL);
embeddedartists 13:57e65aba9802 164 }
embeddedartists 13:57e65aba9802 165
embeddedartists 13:57e65aba9802 166 void AppImageViewer::runToCompletion()
embeddedartists 13:57e65aba9802 167 {
embeddedartists 13:57e65aba9802 168 // Alternative 1: use the calling thread's context to run in
embeddedartists 13:57e65aba9802 169 bool done = false;
embeddedartists 13:57e65aba9802 170 draw();
embeddedartists 13:57e65aba9802 171 _btn->setAction(buttonClicked, (uint32_t)&done);
embeddedartists 13:57e65aba9802 172 void* oldFB = _disp->swapFramebuffer(_fb1);
embeddedartists 13:57e65aba9802 173
embeddedartists 13:57e65aba9802 174 _active = 1;
embeddedartists 13:57e65aba9802 175
embeddedartists 13:57e65aba9802 176 Thread* tLoader = new Thread(loaderTask, this, osPriorityNormal, 8192);
embeddedartists 13:57e65aba9802 177
embeddedartists 13:57e65aba9802 178 bool first = true;
embeddedartists 13:57e65aba9802 179 Timer t;
embeddedartists 13:57e65aba9802 180 while(!done) {
embeddedartists 13:57e65aba9802 181 osEvent evt = _mailbox.get(1000);
embeddedartists 13:57e65aba9802 182 if (evt.status == osEventMail) {
embeddedartists 13:57e65aba9802 183 COLOR_T* fb;
embeddedartists 13:57e65aba9802 184 if (_active == 1) {
embeddedartists 13:57e65aba9802 185 // render on the second frame buffer
embeddedartists 13:57e65aba9802 186 fb = (COLOR_T*)_fb2;
embeddedartists 13:57e65aba9802 187 } else {
embeddedartists 13:57e65aba9802 188 // render on the first frame buffer
embeddedartists 13:57e65aba9802 189 fb = (COLOR_T*)_fb1;
embeddedartists 13:57e65aba9802 190 }
embeddedartists 13:57e65aba9802 191 _win->fb = fb;
embeddedartists 13:57e65aba9802 192 Image::ImageData_t* data = (Image::ImageData_t*)evt.value.p;
embeddedartists 28:be5b06633d98 193 if ((data->width < _disp->width()) || (data->height < _disp->height())) {
embeddedartists 28:be5b06633d98 194 // clear display if the image isn't fullscreen
embeddedartists 28:be5b06633d98 195 memset(_win->fb, 0, _disp->fbSize());
embeddedartists 28:be5b06633d98 196 }
embeddedartists 28:be5b06633d98 197 swim_put_image_xy(_win, (COLOR_T*)data->pixels, data->width, data->height, (_disp->width()-data->width)/2, (_disp->height()-data->height)/2);
embeddedartists 18:715f542538b3 198 free(data->pointerToFree);
embeddedartists 13:57e65aba9802 199 _mailbox.free(data);
embeddedartists 13:57e65aba9802 200 if (first) {
embeddedartists 13:57e65aba9802 201 first = false;
embeddedartists 13:57e65aba9802 202 t.start();
embeddedartists 13:57e65aba9802 203 } else {
embeddedartists 13:57e65aba9802 204 while (t.read_ms() < 2000) {
embeddedartists 13:57e65aba9802 205 Thread::wait(100);
embeddedartists 13:57e65aba9802 206 }
embeddedartists 13:57e65aba9802 207 }
embeddedartists 13:57e65aba9802 208 _disp->setFramebuffer(fb);
embeddedartists 13:57e65aba9802 209 _active = (_active == 1 ? 2 : 1);
embeddedartists 13:57e65aba9802 210 t.reset();
embeddedartists 13:57e65aba9802 211 } else if (tLoader->get_state() == Thread::Inactive) {
embeddedartists 13:57e65aba9802 212 // No more images in the queue and the loader thread
embeddedartists 13:57e65aba9802 213 // has completed its search
embeddedartists 13:57e65aba9802 214 break;
embeddedartists 13:57e65aba9802 215 }
embeddedartists 13:57e65aba9802 216 }
embeddedartists 13:57e65aba9802 217
embeddedartists 13:57e65aba9802 218 delete tLoader;
embeddedartists 13:57e65aba9802 219
embeddedartists 13:57e65aba9802 220 // The button must be drawn on the current framebuffer
embeddedartists 13:57e65aba9802 221 _btn->draw(_win->fb);
embeddedartists 13:57e65aba9802 222
embeddedartists 16:77f4f42eb6a7 223 // Wait for touches, but the AppLauncher is already listening
embeddedartists 16:77f4f42eb6a7 224 // for new touch event and sends a signal to its thread which
embeddedartists 16:77f4f42eb6a7 225 // is the same as runs this function so it is enough to wait
embeddedartists 16:77f4f42eb6a7 226 // for that signal.
embeddedartists 13:57e65aba9802 227 TouchPanel* touch = DMBoard::instance().touchPanel();
embeddedartists 16:77f4f42eb6a7 228 touch_coordinate_t coord;
embeddedartists 13:57e65aba9802 229 while(!done) {
embeddedartists 16:77f4f42eb6a7 230 Thread::signal_wait(0x1);
embeddedartists 13:57e65aba9802 231 if (touch->read(coord) == TouchPanel::TouchError_Ok) {
embeddedartists 13:57e65aba9802 232 if (_btn->handle(coord.x, coord.y, coord.z > 0)) {
embeddedartists 13:57e65aba9802 233 _btn->draw();
embeddedartists 13:57e65aba9802 234 }
embeddedartists 13:57e65aba9802 235 }
embeddedartists 13:57e65aba9802 236 }
embeddedartists 13:57e65aba9802 237
embeddedartists 13:57e65aba9802 238 // User has clicked the button, restore the original FB
embeddedartists 13:57e65aba9802 239 _disp->swapFramebuffer(oldFB);
embeddedartists 13:57e65aba9802 240 swim_window_close(_win);
embeddedartists 13:57e65aba9802 241 }
embeddedartists 13:57e65aba9802 242
embeddedartists 13:57e65aba9802 243 bool AppImageViewer::teardown()
embeddedartists 13:57e65aba9802 244 {
embeddedartists 13:57e65aba9802 245 if (_win != NULL) {
embeddedartists 13:57e65aba9802 246 free(_win);
embeddedartists 13:57e65aba9802 247 _win = NULL;
embeddedartists 13:57e65aba9802 248 }
embeddedartists 13:57e65aba9802 249 if (_fb1 != NULL) {
embeddedartists 13:57e65aba9802 250 free(_fb1);
embeddedartists 13:57e65aba9802 251 _fb1 = NULL;
embeddedartists 13:57e65aba9802 252 }
embeddedartists 13:57e65aba9802 253 if (_fb2 != NULL) {
embeddedartists 13:57e65aba9802 254 free(_fb2);
embeddedartists 13:57e65aba9802 255 _fb2 = NULL;
embeddedartists 13:57e65aba9802 256 }
embeddedartists 13:57e65aba9802 257 if (_btn != NULL) {
embeddedartists 13:57e65aba9802 258 delete _btn;
embeddedartists 13:57e65aba9802 259 _btn = NULL;
embeddedartists 13:57e65aba9802 260 }
embeddedartists 13:57e65aba9802 261 return true;
embeddedartists 13:57e65aba9802 262 }
embeddedartists 13:57e65aba9802 263
embeddedartists 13:57e65aba9802 264