Demo for Embedded World 2015.

Dependencies:   DMBasicGUI DMSupport

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers AppUSBStatus.cpp Source File

AppUSBStatus.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 "EthernetInterface.h"
00020 #include "AppUSBStatus.h"
00021 #include "lpc_swim_image.h"
00022 #include "lpc_swim_font.h"
00023 #include "image_data.h"
00024 #include "BiosLoader.h"
00025 
00026 /******************************************************************************
00027  * Defines and typedefs
00028  *****************************************************************************/
00029  
00030 #define HEADER_X_OFF            (20-5)
00031 #define HEADER_Y_SPACING        (20-5)
00032 #define ITEM_CAPTION_X_OFF      (40-15)
00033 #define ITEM_CAPTION_Y_SPACING  (swim_get_font_height(_win) + 5)
00034 #define ITEM_VALUE_X_OFF        (140-25)
00035 #define COL3_OFF                (230+70)
00036 #define COL4                    (COL3_OFF + ITEM_VALUE_X_OFF - 5)
00037 
00038 #define BTN_WIDTH  40
00039 #define BTN_HEIGHT 40
00040 #define BTN_OFF    20
00041  
00042 #define DEMO_VERSION     "v0.9"
00043 #define DEMO_BUILD_INFO  __DATE__ " " __TIME__
00044 
00045 #define DESCR(__res, __disp) \
00046   (((__res) == ((__disp)->currentResolution())) ? ("Active") : (((__disp)->isSupported(__res)) ? ("Supported") : ("N/A")))
00047 
00048 
00049 static const unsigned char* IMAGES[] = {
00050   img_usb_masstorage,
00051   img_usb_masstorage_ejected,
00052   img_usb_mouse,
00053   img_usb_mouse_ejected,
00054   img_usb_keyboard,
00055   img_usb_keyboard_ejected,
00056 };
00057 static const unsigned int IMAGE_SIZES[] = {
00058   img_size_usb_masstorage,
00059   img_size_usb_masstorage_ejected,
00060   img_size_usb_mouse,
00061   img_size_usb_mouse_ejected,
00062   img_size_usb_keyboard,
00063   img_size_usb_keyboard_ejected,
00064 };
00065 static const char* CAPTIONS[] = {
00066   "Memory Stick",
00067   "No Memory Stick",
00068   "Mouse",
00069   "No Mouse",
00070   "Keyboard",
00071   "No Keyboard",
00072 };
00073 
00074 /******************************************************************************
00075  * Global variables
00076  *****************************************************************************/
00077 
00078 extern bool msdConnected;
00079 extern bool keyboardConnected;
00080 extern bool mouseConnected;
00081 
00082 /******************************************************************************
00083  * Private functions
00084  *****************************************************************************/
00085 
00086 static void buttonClicked(uint32_t x)
00087 {
00088   bool* done = (bool*)x;
00089   *done = true;
00090 }
00091 
00092 void AppUSBStatus::draw()
00093 {
00094     // Prepare fullscreen
00095     swim_window_open(_win, 
00096                    _disp->width(), _disp->height(),         // full size
00097                    (COLOR_T*)_fb,
00098                    0,0,_disp->width()-1, _disp->height()-1, // window position and size
00099                    0,                                       // border
00100                    BLACK, WHITE, BLACK);                     // colors: pen, backgr, forgr
00101     //swim_set_title(_win, "USB Status", BLACK);
00102     
00103     // Start by drawing all USB Devices disconnected. Each device is drawn in
00104     // its own window so that the positioning information can be kept here
00105     int images = NumImages/2;
00106     int xspace = (_disp->width() - (_images[0].width * images)) / 4;
00107     int yoff = (_disp->height() - _images[0].height)/3;
00108     int xoff = xspace;
00109     for (int i = 1; i < NumImages; i+=2) {
00110       swim_window_open(&_imageWindows[i/2], 
00111                        _disp->width(), _disp->height(),         // full size
00112                        (COLOR_T*)_fb,
00113                        xoff,yoff,xoff+_images[0].width-1, yoff+_images[0].height+20-1, // window position and size
00114                        0,                                       // border
00115                        BLACK, WHITE, BLACK);                     // colors: pen, backgr, forgr
00116       swim_put_image(&_imageWindows[i/2], _images[i].pixels, _images[i].width, _images[i].height);
00117         
00118       swim_put_text_centered_win(&_imageWindows[i/2], CAPTIONS[i], _images[i].height);
00119       xoff += _images[i].width + xspace;
00120     }
00121 //    
00122 
00123 //    char buff[120];
00124 //    
00125 //    // Column 1
00126 //    swim_put_text_xy(_win, "Demo:", HEADER_X_OFF, HEADER_Y_SPACING);
00127 //    swim_put_text_xy(_win, "Version:", ITEM_CAPTION_X_OFF, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 1);
00128 //    swim_put_text_xy(_win, "Build:", ITEM_CAPTION_X_OFF, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 2);
00129 
00130 //    swim_put_text_xy(_win, "Network:", HEADER_X_OFF, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 4);
00131 //    swim_put_text_xy(_win, "DHCP/Static:", ITEM_CAPTION_X_OFF, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 5);
00132 //    swim_put_text_xy(_win, "IP Address:", ITEM_CAPTION_X_OFF, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 6);
00133 //    swim_put_text_xy(_win, "NetMask:", ITEM_CAPTION_X_OFF, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 7);
00134 //    swim_put_text_xy(_win, "Gateway:", ITEM_CAPTION_X_OFF, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 8);
00135 //    swim_put_text_xy(_win, "MAC Address:", ITEM_CAPTION_X_OFF, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 9);
00136 
00137 //    char mac[6];
00138 //    mbed_mac_address(mac);
00139 //    snprintf(buff, 19, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
00140 //    swim_put_text_xy(_win, buff, ITEM_CAPTION_X_OFF+10, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 10);
00141 
00142 //    // Column 2
00143 //    swim_put_text_xy(_win, DEMO_VERSION, ITEM_VALUE_X_OFF-20, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 1);
00144 //    swim_put_text_xy(_win, DEMO_BUILD_INFO, ITEM_VALUE_X_OFF-20, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 2);
00145 
00146 //    swim_put_text_xy(_win, ethUsingDHCP?"DHCP":"Static IP", ITEM_VALUE_X_OFF-20, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 5);
00147 //    if (ethInitialized) {
00148 //        swim_put_text_xy(_win, eth.getIPAddress(), ITEM_VALUE_X_OFF-20, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 6);
00149 //        swim_put_text_xy(_win, eth.getNetworkMask(), ITEM_VALUE_X_OFF-20, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 7);
00150 //        swim_put_text_xy(_win, eth.getGateway(), ITEM_VALUE_X_OFF-20, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 8);
00151 //        //swim_put_text_xy(_win, eth.getMACAddress(), ITEM_VALUE_X_OFF, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 4);
00152 //    } else {
00153 //        swim_put_text_xy(_win, "Not Initialized", ITEM_VALUE_X_OFF-20, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 6);
00154 //        swim_put_text_xy(_win, "Not Initialized", ITEM_VALUE_X_OFF-20, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 7);
00155 //        swim_put_text_xy(_win, "Not Initialized", ITEM_VALUE_X_OFF-20, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 8);    
00156 //    }
00157 
00158 //    // Column 3
00159 //    swim_put_text_xy(_win, "Display:", COL3_OFF+HEADER_X_OFF, HEADER_Y_SPACING);
00160 //    swim_put_text_xy(_win, "Size:", COL3_OFF+ITEM_CAPTION_X_OFF, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 1);
00161 //    swim_put_text_xy(_win, "Landscape:", COL3_OFF+ITEM_CAPTION_X_OFF, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 2);
00162 //    swim_put_text_xy(_win, "Resolutions:", COL3_OFF+ITEM_CAPTION_X_OFF, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 3);
00163 //    swim_put_text_xy(_win, "16bit rgb565:", COL3_OFF+ITEM_CAPTION_X_OFF+10, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 4);
00164 //    swim_put_text_xy(_win, "18bit rgb666:", COL3_OFF+ITEM_CAPTION_X_OFF+10, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 5);
00165 //    swim_put_text_xy(_win, "24bit rgb888:", COL3_OFF+ITEM_CAPTION_X_OFF+10, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 6);
00166 
00167 //    swim_put_text_xy(_win, "BIOS:", COL3_OFF+HEADER_X_OFF, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 8);
00168 //    //swim_put_text_xy(_win, "Info:", COL3_OFF+ITEM_CAPTION_X_OFF, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 8);
00169 //    //swim_put_text_xy(_win, "Board Type:", COL3_OFF+ITEM_CAPTION_X_OFF, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 9);
00170 //    {
00171 //        uint8_t type, maj, min, rev;
00172 //        BiosLoader::instance().getBiosStats(type, maj, min, rev);
00173 //        //snprintf(buff, 19, "v%u.%u.%u", maj, min, rev);
00174 //        //swim_put_text_xy(_win, buff, COL4 -20, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 8);
00175 //        //snprintf(buff, 19, "%u", type);
00176 //        //swim_put_text_xy(_win, buff, COL4 -20, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 9);
00177 //        snprintf(buff, 25, "v%u.%u.%u  (board type %u)", maj, min, rev, type);
00178 //        swim_put_text_xy(_win, buff, COL3_OFF+ITEM_CAPTION_X_OFF, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 9);
00179 //    }
00180 
00181 //    // Column 4
00182 //    sprintf(buff, "%d x %d pixels", _disp->width(), _disp->height());
00183 //    swim_put_text_xy(_win, buff, COL4 -20, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 1);
00184 //    
00185 //    sprintf(buff, "%s", _disp->landscape()?"YES":"NO");
00186 //    swim_put_text_xy(_win, buff, COL4 -20, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 2);
00187 
00188 //    //sprintf(buff, "%s %s", _disp->isSupported(Display::Resolution_16bit_rgb565)?"Supported":"N/A", _disp->currentResolution()==Display::Resolution_16bit_rgb565?"  (Active)":"");
00189 //    sprintf(buff, "%s", DESCR(Display::Resolution_16bit_rgb565, _disp));
00190 //    swim_put_text_xy(_win, buff, COL4, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 4);
00191 //    
00192 //    //sprintf(buff, "%s %s", _disp->isSupported(Display::Resolution_18bit_rgb666)?"Supported":"N/A", _disp->currentResolution()==Display::Resolution_18bit_rgb666?"  (Active)":"");
00193 //    sprintf(buff, "%s", DESCR(Display::Resolution_18bit_rgb666, _disp));
00194 //    swim_put_text_xy(_win, buff, COL4, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 5);
00195 //    
00196 //    //sprintf(buff, "%s %s", _disp->isSupported(Display::Resolution_24bit_rgb888)?"Supported":"N/A", _disp->currentResolution()==Display::Resolution_24bit_rgb888?"  (Active)":"");
00197 //    sprintf(buff, "%s", DESCR(Display::Resolution_24bit_rgb888, _disp));
00198 //    swim_put_text_xy(_win, buff, COL4, HEADER_Y_SPACING + ITEM_CAPTION_Y_SPACING * 6);
00199 
00200     _btn = new ImageButton(_win->fb, _win->xpmax - BTN_OFF - BTN_WIDTH, _win->ypmax - BTN_OFF - BTN_HEIGHT, BTN_WIDTH, BTN_HEIGHT);
00201     _btn->loadImages(img_ok, img_size_ok);
00202     _btn->draw();
00203 }
00204 
00205 void AppUSBStatus::updateStatus(Ids id)    
00206 {
00207     SWIM_WINDOW_T* pWin = &_imageWindows[id/2];
00208     swim_clear_screen(pWin, WHITE);
00209     swim_put_image(pWin, _images[id].pixels, _images[id].width, _images[id].height);    
00210     swim_put_text_centered_win(pWin, CAPTIONS[id], _images[id].height);
00211 }
00212 
00213 /******************************************************************************
00214  * Public functions
00215  *****************************************************************************/
00216 
00217 AppUSBStatus::AppUSBStatus() : _disp(NULL), _win(NULL), _fb(NULL), _btn(NULL)
00218 {
00219   for (int i = 0; i < NumImages; i++) {
00220     _images[i].pointerToFree = NULL;
00221     _images[i].pixels = NULL;
00222   }
00223 }
00224 
00225 AppUSBStatus::~AppUSBStatus()
00226 {
00227     teardown();
00228 }
00229 
00230 bool AppUSBStatus::setup()
00231 {
00232     RtosLog* log = DMBoard::instance().logger();
00233 
00234     _disp = DMBoard::instance().display();
00235     _win = (SWIM_WINDOW_T*)malloc(sizeof(SWIM_WINDOW_T));
00236     _fb = _disp->allocateFramebuffer();
00237 
00238     if (_win == NULL || _fb == NULL) {
00239         log->printf("Failed to allocate memory for framebuffer\r\n");
00240         return false;
00241     }
00242     
00243     for (int i = 0; i < NumImages; i++) {
00244         if (Image::decode(IMAGES[i], IMAGE_SIZES[i], Image::RES_16BIT, &_images[i]) != 0) {
00245             log->printf("Failed to load image %d of %d\n", i+1, NumImages);
00246             return false;
00247         }
00248     }
00249     
00250     return true;
00251 }
00252 
00253 void AppUSBStatus::runToCompletion()
00254 {
00255     // Alternative 1: use the calling thread's context to run in
00256     bool done = false;
00257     draw();
00258     _btn->setAction(buttonClicked, (uint32_t)&done);
00259     void* oldFB = _disp->swapFramebuffer(_fb);
00260     
00261     // Wait for touches, but the AppLauncher is already listening
00262     // for new touch event and sends a signal to its thread which
00263     // is the same as runs this function so it is enough to wait
00264     // for that signal.
00265     TouchPanel* touch = DMBoard::instance().touchPanel();
00266     touch_coordinate_t coord;
00267     bool lastMassStorage = false;
00268     bool lastMouse = false;
00269     bool lastKeyboard = false;
00270     while(!done) {
00271       Thread::signal_wait(0x1, 500);
00272       if (touch->read(coord) == TouchPanel::TouchError_Ok) {
00273         if (_btn->handle(coord.x, coord.y, coord.z > 0)) {
00274             _btn->draw();
00275         }
00276       }
00277       if (lastMassStorage != msdConnected) {
00278         lastMassStorage = msdConnected;
00279         updateStatus(lastMassStorage ? USBHost_MassStorage_Inserted : USBHost_MassStorage_Ejected);
00280       }
00281       if (lastKeyboard != keyboardConnected) {
00282         lastKeyboard = keyboardConnected;
00283         updateStatus(lastKeyboard ? USBHost_Keyboard_Inserted : USBHost_Keyboard_Ejected);
00284       }
00285       if (lastMouse != mouseConnected) {
00286         lastMouse = mouseConnected;
00287         updateStatus(lastMouse ? USBHost_Mouse_Inserted : USBHost_Mouse_Ejected);
00288       }
00289     }
00290     
00291     // User has clicked the button, restore the original FB
00292     _disp->swapFramebuffer(oldFB);
00293     swim_window_close(_win);
00294 }
00295 
00296 bool AppUSBStatus::teardown()
00297 {
00298     if (_win != NULL) {
00299         free(_win);
00300         _win = NULL;
00301     }
00302     if (_fb != NULL) {
00303         free(_fb);
00304         _fb = NULL;
00305     }
00306     if (_btn != NULL) {
00307         delete _btn;
00308         _btn = NULL;
00309     }
00310     for (int i = 0; i < NumImages; i++) {
00311         if (_images[i].pointerToFree != NULL) {
00312             free(_images[i].pointerToFree);
00313             _images[i].pointerToFree = NULL;
00314         }    
00315     }
00316     return true;
00317 }
00318 
00319 
00320