A basic graphics package for the LPC4088 Display Module.

Dependents:   lpc4088_displaymodule_demo_sphere sampleGUI sampleEmptyGUI lpc4088_displaymodule_fs_aid ... more

Fork of DMBasicGUI by EmbeddedArtists AB

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers AppLauncher.cpp Source File

AppLauncher.cpp

00001 /*
00002  *  Copyright 2014 Embedded Artists AB
00003  *
00004  *  Licensed under the Apache License, Version 2.0 (the "License");
00005  *  you may not use this file except in compliance with the License.
00006  *  You may obtain a copy of the License at
00007  *
00008  *    http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  *  Unless required by applicable law or agreed to in writing, software
00011  *  distributed under the License is distributed on an "AS IS" BASIS,
00012  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *  See the License for the specific language governing permissions and
00014  *  limitations under the License.
00015  */
00016 
00017 
00018 #include "mbed.h"
00019 #include "AppLauncher.h"
00020 #include "lpc_swim_font.h"
00021 #include "Button.h"
00022 #include "ImageButton.h"
00023 
00024 /******************************************************************************
00025  * Defines and typedefs
00026  *****************************************************************************/
00027  
00028 #define APP_PREFIX  "[Launcher] "
00029 
00030 #define NO_APPLICATION  (-1)
00031 
00032 #define APP_SIGID_TOUCH  0x1
00033 
00034 /******************************************************************************
00035  * Private variables
00036  *****************************************************************************/
00037 
00038 static int appToLaunch = NO_APPLICATION;
00039 static osThreadId appThread;
00040 
00041 /******************************************************************************
00042  * Private functions
00043  *****************************************************************************/
00044 
00045 static void buttonClicked(uint32_t x)
00046 {
00047     if (appToLaunch == NO_APPLICATION) {
00048         appToLaunch = (int)x;
00049     }
00050 }
00051 
00052 void AppLauncher::draw()
00053 {
00054     // Prepare fullscreen
00055     swim_window_open(_win, 
00056                      _disp->width(), _disp->height(),         // full size
00057                      (COLOR_T*)_fb,
00058                      0,0,_disp->width()-1, _disp->height()-1, // window position and size
00059                      1,                                     // border
00060                      WHITE, BLACK, BLACK);                    // colors: pen, backgr, forgr
00061     swim_set_title(_win, "Demo Program", BLACK);
00062 
00063     if (_supportsCalibration) {
00064       const char* msg = "(Press physical UserButton >2s to calibrate touch)";
00065       int w, h;
00066       swim_get_string_bounds(_win, msg, &w, &h);
00067       swim_put_text_xy(_win, msg, (_disp->width()-w)/2, _disp->height()-h*4);
00068     }
00069     
00070     for (int i = 0; i < _usedButtons; i++) {
00071         _buttons[i]->draw();
00072     }
00073 }
00074 
00075 void AppLauncher::onTouchEvent()
00076 {
00077     _newTouchEvent = true;
00078     osSignalSet(appThread, APP_SIGID_TOUCH);
00079 }
00080 
00081 void AppLauncher::onButtonEvent()
00082 {
00083     _newButtonEvent = true;
00084     osSignalSet(appThread, APP_SIGID_TOUCH);
00085 }
00086 
00087 static void onTimeoutEvent(void const* arg)
00088 {
00089     *((bool*)arg) = true;
00090     osSignalSet(appThread, APP_SIGID_TOUCH);
00091 }
00092 
00093 /******************************************************************************
00094  * Public functions
00095  *****************************************************************************/
00096 
00097 AppLauncher::AppLauncher() : _disp(NULL), _win(NULL), _fb(NULL), _usedButtons(0)
00098 {
00099     for (int i = 0; i < NumberOfButtons; i++) {
00100         _buttons[i] = NULL;
00101     }
00102     bool r;
00103     int n;
00104     if (DMBoard::instance().touchPanel()->info(&r, &n, &_supportsCalibration) != TouchPanel::TouchError_Ok) {
00105       _supportsCalibration = false;
00106     }
00107 }
00108 
00109 AppLauncher::~AppLauncher()
00110 {
00111     teardown();
00112 }
00113 
00114 bool AppLauncher::setup()
00115 {
00116     RtosLog* log = DMBoard::instance().logger();
00117 
00118     _disp = DMBoard::instance().display();
00119     _win = (SWIM_WINDOW_T*)malloc(sizeof(SWIM_WINDOW_T));
00120     _fb = _disp->allocateFramebuffer();
00121     
00122     if (_win == NULL || _fb == NULL) {
00123         log->printf(APP_PREFIX"Failed to allocate memory for framebuffer\r\n");
00124         return false;
00125     }
00126     
00127     return true;
00128 }
00129 
00130 void AppLauncher::runToCompletion()
00131 {
00132     DMBoard* board = &DMBoard::instance();
00133     RtosLog* log = board->logger();
00134     
00135     appThread = osThreadGetId();
00136 
00137     // Draw something on the framebuffer before using it so that it doesn't look garbled
00138     draw();
00139     
00140     // Start display in default mode (16-bit)
00141     Display::DisplayError disperr = _disp->powerUp(_fb);
00142     if (disperr != Display::DisplayError_Ok) {
00143         log->printf(APP_PREFIX"Failed to initialize the display, got error %d\r\n", disperr);
00144         return;
00145     }
00146     
00147     // To keep track of the button pushes
00148     bool buttonPressed = false;
00149     bool buttonTimeout = false;
00150     InterruptIn button(P2_10);
00151     button.rise(callback(this, &AppLauncher::onButtonEvent));
00152     button.fall(callback(this, &AppLauncher::onButtonEvent));
00153     //RtosTimer  buttonTimer(onTimeoutEvent, osTimerOnce, &buttonTimeout);
00154     EventQueue buttonTimer(4*EVENTS_EVENT_SIZE);
00155     int buttonTimerId = buttonTimer.call_in(2000, onTimeoutEvent, &buttonTimeout);
00156     
00157     // Wait for touches
00158     TouchPanel* touch = board->touchPanel();
00159     //FunctionPointer* fpOld = touch->setListener(new FunctionPointer(this, &AppLauncher::onTouchEvent));
00160     touch->setListener(callback(this, &AppLauncher::onTouchEvent));
00161     touch_coordinate_t coord;
00162     while (true) {
00163         ThisThread::flags_wait_any(APP_SIGID_TOUCH);
00164         if (_newTouchEvent) {
00165           if (buttonPressed) {
00166             // cancel
00167             buttonPressed = false;
00168             //buttonTimer.stop();
00169             buttonTimer.cancel(buttonTimerId);
00170           }
00171           _newTouchEvent = false;
00172           if (touch->read(coord) != TouchPanel::TouchError_Ok) {
00173             log->printf("Failed to read touch coordinate\n");
00174             continue;
00175           }
00176           // Process the touch coordinate for each button
00177           for (int i = 0; i < NumberOfButtons; i++) {
00178             if (_buttons[i] != NULL) {
00179               if (_buttons[i]->handle(coord.x, coord.y, coord.z > 0)) {
00180                 _buttons[i]->draw();
00181               }
00182             }
00183           }
00184         } else if (buttonTimeout) {
00185           if (board->buttonPressed()) {
00186             appToLaunch = CalibrationApp;
00187           }
00188           buttonPressed = false;
00189           buttonTimeout = false;
00190         } else if (_newButtonEvent) {
00191           _newButtonEvent = false;
00192           if (board->buttonPressed()) {
00193             buttonPressed = true;
00194             //buttonTimer.start(2000);
00195             buttonTimer.dispatch(0);            
00196           } else {
00197             buttonPressed = false;
00198             //buttonTimer.stop();
00199             buttonTimer.cancel(buttonTimerId);
00200           }
00201           continue;
00202         }
00203         
00204         if (appToLaunch != NO_APPLICATION) {
00205             App* a = NULL;
00206             if (_callback != NULL) {
00207                 a = _callback(appToLaunch);
00208             }
00209             if (a != NULL) {
00210                 if (a->setup()) {
00211                     a->runToCompletion();
00212                     a->teardown();
00213                 }
00214                 delete a;
00215             }
00216             appToLaunch = NO_APPLICATION;
00217         }
00218     }
00219     
00220     // restore old touch listener (get our listener in return)
00221     //fpOld = touch->setListener(fpOld);
00222     //delete fpOld;
00223 }
00224 
00225 bool AppLauncher::teardown()
00226 {
00227     if (_win != NULL) {
00228         free(_win);
00229         _win = NULL;
00230     }
00231     if (_fb != NULL) {
00232         free(_fb);
00233         _fb = NULL;
00234     }
00235     for (int i = 0; i < NumberOfButtons; i++) {
00236         _buttons[i] = NULL;
00237         if (_buttons[i] != NULL) {
00238             delete _buttons[i];
00239             _buttons[i] = NULL;
00240         }
00241     }
00242     return true;
00243 }
00244 
00245 void AppLauncher::setAppCreatorFunc(App*(*callback)(uint32_t buttonID))
00246 {
00247     _callback = callback;
00248 }
00249 
00250 bool AppLauncher::addButton(uint32_t buttonID, const char* caption)
00251 {
00252     int idx = _usedButtons++;
00253     int xspace = ((_disp->width() - ButtonColumns * ButtonWidth) / (ButtonColumns + 1));
00254     int yspace = ((_disp->height() - TitleHeight - ButtonRows * ButtonHeight) / (ButtonRows + 1));
00255     
00256     _buttons[idx] = new Button(caption, (COLOR_T*)_fb, 
00257                               xspace + (ButtonWidth + xspace)*(idx%ButtonColumns), 
00258                               TitleHeight + yspace + (ButtonHeight + yspace)*(idx/ButtonColumns), 
00259                               ButtonWidth, ButtonHeight);
00260     _buttons[idx]->setAction(buttonClicked, buttonID);
00261     //_buttons[idx]->draw();
00262     return true;
00263 }
00264 
00265 bool AppLauncher::addImageButton(uint32_t buttonID, const char* imgUp, const char* imgDown)
00266 {
00267     return addImageButton(buttonID, NULL, BLACK, imgUp, imgDown);
00268 }
00269 
00270 bool AppLauncher::addImageButton(uint32_t buttonID, const char* caption, COLOR_T color, const char* imgUp, const char* imgDown)
00271 {
00272     int idx = _usedButtons++;
00273     int xspace = ((_disp->width() - ButtonColumns * 64) / (ButtonColumns + 1));
00274     int yspace = ((_disp->height() - TitleHeight - ButtonRows * 64) / (ButtonRows + 1));
00275     int yoff = (caption == NULL) ? 0 : -15; // compensate for caption taking up space
00276     
00277     ImageButton* img =  new ImageButton((COLOR_T*)_fb, 
00278                               xspace + (64 + xspace)*(idx%ButtonColumns), 
00279                               TitleHeight + yspace + (64 + yspace)*(idx/ButtonColumns) + yoff, 
00280                               64, 64, caption, color);
00281     if (img->loadImages(imgUp, imgDown)) {
00282       _buttons[idx] = img;
00283       _buttons[idx]->setAction(buttonClicked, buttonID);
00284       //_buttons[idx]->draw();
00285       return true;
00286     } else {
00287       //DMBoard::instance().logger()->printf("Failed to load image for buttonID %u, %s[%s]\n", buttonID, imgUp, imgDown==NULL?"":imgDown);
00288       return false;
00289     }
00290 }
00291 
00292 bool AppLauncher::addImageButton(uint32_t buttonID, const unsigned char* imgUp, unsigned int imgUpSize, const unsigned char* imgDown, unsigned int imgDownSize)
00293 {
00294     return addImageButton(buttonID, NULL, BLACK, imgUp, imgUpSize, imgDown, imgDownSize);
00295 }
00296 
00297 bool AppLauncher::addImageButton(uint32_t buttonID, const char* caption, COLOR_T color, const unsigned char* imgUp, unsigned int imgUpSize, const unsigned char* imgDown, unsigned int imgDownSize)
00298 {
00299     int idx = _usedButtons++;
00300     int xspace = ((_disp->width() - ButtonColumns * 64) / (ButtonColumns + 1));
00301     int yspace = ((_disp->height() - TitleHeight - ButtonRows * 64) / (ButtonRows + 1));
00302     int yoff = (caption == NULL) ? 0 : -15; // compensate for caption taking up space
00303     
00304     ImageButton* img =  new ImageButton((COLOR_T*)_fb, 
00305                               xspace + (64 + xspace)*(idx%ButtonColumns), 
00306                               TitleHeight + yspace + (64 + yspace)*(idx/ButtonColumns) + yoff, 
00307                               64, 64, caption, color);
00308     if (img->loadImages(imgUp, imgUpSize, imgDown, imgDownSize)) {
00309       _buttons[idx] = img;
00310       _buttons[idx]->setAction(buttonClicked, buttonID);
00311       //_buttons[idx]->draw();
00312       return true;
00313     } else {
00314       //DMBoard::instance().logger()->printf("Failed to load image for buttonID %u, %s[%s]\n", buttonID, imgUp, imgDown==NULL?"":imgDown);
00315       return false;
00316     }
00317 }