Support for the emWin GUI library from Segger.

Dependents:   lpc4088_displaymodule_emwin

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers EwHAL.cpp Source File

EwHAL.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 #include "EwHAL.h"
00017 #include "GUI.h"
00018 #include "GUIDRV_Lin.h"
00019 #include "rtos.h"
00020 
00021 
00022 /******************************************************************************
00023  * Defines and typedefs
00024  *****************************************************************************/
00025 
00026 /* This value is not important but the same value must be used by both the
00027    GUI_X_WaitEvent() and the GUI_X_SignalEvent() functions. */
00028 #define EMWIN_TASK_SIGNAL   (0x2)
00029 
00030 /******************************************************************************
00031  * Local variables
00032  *****************************************************************************/
00033 
00034 static EwHAL* _hal = NULL;
00035 static int _gettimeoffset = 0;
00036 static Semaphore* _emSem;
00037 
00038 static Timer _ewTimer;
00039 static osThreadId _emTask = 0;
00040 
00041 /******************************************************************************
00042  * Private Functions
00043  *****************************************************************************/
00044 
00045 void EwHAL::handleTouchEvent() {
00046     GUI_PID_STATE ewCoord = {0};
00047 
00048     if (_touch->read(_coord) == TouchPanel::TouchError_Ok) {
00049         ewCoord.x = _coord.x;
00050         ewCoord.y = _coord.y;
00051         ewCoord.Pressed = (_coord.z == 0) ? 0 : 1;
00052         GUI_PID_StoreState(&ewCoord);
00053     }
00054 }
00055 
00056 /******************************************************************************
00057  * Public Functions
00058  *****************************************************************************/
00059 
00060 EwHAL::EwHAL(int numFB, uint32_t extraMem) {
00061 
00062     RtosLog* log = DMBoard::instance().logger();
00063     _display = DMBoard::instance().display();
00064     _touch = DMBoard::instance().touchPanel();
00065     
00066     _width = _display->width();
00067     _height = _display->height();
00068     _fbSz = _display->fbSize();
00069     _numFB = numFB;
00070     
00071     do {
00072         if (numFB < 1) {
00073             log->printf("Failed. Must have at least one frame buffer, wanted %d\n", numFB);
00074             break;
00075         }
00076 
00077         _fb = (uint32_t)_display->allocateFramebuffers(numFB);
00078         if (_fb == 0) {
00079             log->printf("Failed to allocate memory for %d framebuffer(s)\n", numFB);
00080             break;
00081         }
00082         memset((void*)_fb, 0x0, _fbSz * numFB);
00083         
00084         _display->setFramebuffer((void*)_fb);
00085     
00086         _memSz = extraMem;
00087         _mem = (uint32_t)malloc(_memSz);
00088         if (_mem == 0) {
00089             log->printf("Failed to allocate memory block for emwin (wanted %u bytes)\n", _memSz);
00090             break;
00091         }
00092         memset((void*)_mem, 0x0, _memSz);
00093         
00094         _fp = new FunctionPointer(this, &EwHAL::handleTouchEvent);
00095         _touch->setListener(_fp);
00096         
00097         _hal = this;
00098     } while(false); 
00099 }
00100 
00101 EwHAL::~EwHAL() {
00102     _hal = NULL;
00103     if (_mem != 0) {
00104         free((void*)_mem);
00105         _mem = NULL;
00106     }
00107     if (_fb != 0) {
00108         free((void*)_fb);
00109         _fb = NULL;
00110     }
00111     if (_fp != NULL) {
00112         _touch->setListener(NULL);
00113         delete(_fp);
00114     }
00115 }
00116 
00117 void EwHAL::showFrameBuffer(int id) {
00118     if (id >= 0 && id < getNumFrameBuffers()) {
00119         _display->setFramebuffer((void*)(_fb + id * _fbSz));
00120     }
00121 }
00122 
00123 /******************************************************************************
00124  * emWin HAL functions
00125  *****************************************************************************/
00126 
00127 /*********************************************************************
00128  *
00129  *       GUI_X_Config
00130  *
00131  * Purpose:
00132  *   Called during the initialization process in order to set up the
00133  *   available memory for the GUI.
00134  */
00135 void GUI_X_Config(void) {
00136 
00137     if (_hal == NULL) return;
00138 
00139     //
00140     // Assign memory to emWin
00141     //
00142 
00143     GUI_ALLOC_AssignMemory(_hal->getMemoryBlockAddress(), _hal->getMemoryBlockSize());
00144     GUI_ALLOC_SetAvBlockSize(0x80);
00145     
00146     _emTask = Thread::gettid();
00147 
00148     GUI_SetSignalEventFunc(GUI_X_SignalEvent);
00149     GUI_SetWaitEventFunc(GUI_X_WaitEvent);
00150     GUI_SetWaitEventTimedFunc(GUI_X_WaitEventTimed);
00151 }
00152 
00153 /*********************************************************************
00154  *
00155  *       LCD_X_Config
00156  *
00157  * Purpose:
00158  *   Called during the initialization process in order to set up the
00159  *   display driver configuration.
00160  */
00161 void LCD_X_Config(void) {
00162 
00163     if (_hal == NULL) return;
00164     
00165     //
00166     // Initialize MultiBuffering
00167     //
00168     if (_hal->getNumFrameBuffers() > 1) {
00169         GUI_MULTIBUF_Config(_hal->getNumFrameBuffers());
00170     }
00171      
00172 
00173     GUI_DEVICE_CreateAndLink(&GUIDRV_Lin_16_API, GUICC_M565, 0, 0);
00174 
00175     //
00176     // Display driver configuration, required for Lin-driver
00177     //
00178     LCD_SetPosEx(0, 0, 0);
00179     if (LCD_GetSwapXYEx(0)) {
00180         LCD_SetSizeEx  (0, _hal->getDisplayHeight(), _hal->getDisplayWidth());
00181         LCD_SetVSizeEx (0, _hal->getDisplayHeight(), _hal->getDisplayWidth());
00182     } else {
00183         LCD_SetSizeEx  (0, _hal->getDisplayWidth(), _hal->getDisplayHeight());
00184         LCD_SetVSizeEx (0, _hal->getDisplayWidth(), _hal->getDisplayHeight());
00185     }
00186     LCD_SetVRAMAddrEx(0, (void*)0);
00187     
00188     // TODO: Add Custom callback routine (DMA) for copying the buffers
00189     //       Explained in the emWin User Manual rev 5.26 section 21.4.1
00190 }
00191 
00192 /*********************************************************************
00193  *
00194  *       LCD_X_DisplayDriver
00195  *
00196  * Purpose:
00197  *   This function is called by the display driver for several purposes.
00198  *   To support the according task the routine needs to be adapted to
00199  *   the display controller. Please note that the commands marked with
00200  *   'optional' are not cogently required and should only be adapted if
00201  *   the display controller supports these features.
00202  *
00203  * Parameter:
00204  *   LayerIndex - Index of layer to be configured
00205  *   Cmd        - Please refer to the details in the switch statement below
00206  *   pData      - Pointer to a LCD_X_DATA structure
00207  *
00208  * Return Value:
00209  *   < -1 - Error
00210  *     -1 - Command not handled
00211  *      0 - Ok
00212  */
00213 int LCD_X_DisplayDriver(unsigned LayerIndex, unsigned Cmd, void * pData) {
00214     //  LCD_X_SETORG_INFO * pSetOrg;
00215     int r;
00216     U32 TouchOrientation;
00217 
00218     if (_hal == NULL) return -1;
00219 
00220     switch (Cmd) {
00221     //
00222     // Required
00223     //
00224     case LCD_X_INITCONTROLLER:
00225         //
00226         // Called during the initialization process in order to set up the
00227         // display controller and put it into operation. If the display
00228         // controller is not initialized by any external routine this needs
00229         // to be adapted by the customer...
00230         //
00231         // ...
00232 
00233         //
00234         // Set display size and video-RAM address
00235         //
00236         //      LCD_SetSizeEx (800, 480, 0);
00237         //      LCD_SetVSizeEx(800, 480, 0);
00238         LCD_SetVRAMAddrEx(0, (void*)_hal->getFrameBufferAddress());
00239 
00240         TouchOrientation = (GUI_MIRROR_X * LCD_GetMirrorXEx(0)) |
00241                             (GUI_MIRROR_Y * LCD_GetMirrorYEx(0)) |
00242                             (GUI_SWAP_XY  * LCD_GetSwapXYEx (0)) ;
00243         GUI_TOUCH_SetOrientation(TouchOrientation);
00244 
00245         return 0;
00246     case LCD_X_SETORG:
00247         //
00248         // Required for setting the display origin which is passed in the 'xPos' and 'yPos' element of p
00249         //
00250 
00251         // pSetOrg = (LCD_X_SETORG_INFO *)pData;
00252         //        LPC_LCD->UPBASE = VRAM_ADDR_PHYS +
00253         //                (pSetOrg->yPos * YSIZE_PHYS * /*PIXEL_WIDTH*/ 2);  // Needs to be set, before LCDC is enabled
00254 
00255         return 0;
00256     case LCD_X_SHOWBUFFER:
00257         {
00258             LCD_X_SHOWBUFFER_INFO * p = (LCD_X_SHOWBUFFER_INFO *)pData;
00259             //
00260             // Calculate address of the given buffer
00261             //
00262             //unsigned long BufferSize = (XSIZE * YSIZE * BITSPERPIXEL) / 8;
00263             //unsigned long Addr = _VRamBaseAddr + ewGui->getFrameBufferSize() * pData->Index;
00264             //
00265             // Make the given buffer visible
00266             //
00267             _hal->showFrameBuffer(p->Index);
00268             //
00269             // Send a confirmation that the buffer is visible now
00270             //
00271             GUI_MULTIBUF_Confirm(p->Index);
00272         }
00273         return 0;
00274     default:
00275         r = -1;
00276     }
00277 
00278     return r;
00279 }
00280 
00281 
00282 
00283 /*********************************************************************
00284  *
00285  *      Timing:
00286  *                 GUI_X_GetTime()
00287  *                 GUI_X_Delay(int)
00288  *
00289  * Some timing dependent routines require a GetTime and delay function. 
00290  * Default time unit (tick), normally is 1 ms.
00291  */
00292 
00293 int GUI_X_GetTime(void) {
00294     int t = _ewTimer.read_ms();
00295     if (t > 3600000) {
00296         // reset once per hour
00297         _ewTimer.reset();
00298         _gettimeoffset += t;
00299         t = 0;
00300     }
00301     return t + _gettimeoffset;
00302 }
00303 
00304 void GUI_X_Delay(int ms) {
00305     Thread::wait(ms);
00306 }
00307 
00308 /*********************************************************************
00309  *
00310  *       GUI_X_Init()
00311  *
00312  * Note:
00313  *     GUI_X_Init() is called from GUI_Init is a possibility to init
00314  *     some hardware which needs to be up and running before the GUI.
00315  *     If not required, leave this routine blank.
00316  */
00317 void GUI_X_Init(void) {
00318     _ewTimer.start();
00319 }
00320 
00321 
00322 /*********************************************************************
00323  *
00324  *       GUI_X_ExecIdle
00325  *
00326  * Note:
00327  *  Called if WM is in idle state
00328  */
00329 
00330 void GUI_X_ExecIdle(void) {}
00331 
00332 /*********************************************************************
00333  *
00334  *      Multitasking:
00335  *
00336  *                 GUI_X_InitOS()
00337  *                 GUI_X_GetTaskId()
00338  *                 GUI_X_Lock()
00339  *                 GUI_X_Unlock()
00340  *
00341  * Note:
00342  *   The following routines are required only if emWin is used in a
00343  *   true multi task environment, which means you have more than one
00344  *   thread using the emWin API.
00345  *   In this case the
00346  *                       #define GUI_OS 1
00347  *  needs to be in GUIConf.h
00348  */
00349 
00350    
00351 static void emTimeout(void const* args) {
00352     GUI_X_SignalEvent();
00353 }
00354 
00355 void GUI_X_InitOS(void) {
00356     _emSem = new Semaphore(1); 
00357 }
00358 
00359 void GUI_X_Unlock(void) {
00360     _emSem->release();
00361 }
00362 
00363 void GUI_X_Lock(void) {
00364     _emSem->wait();
00365 }
00366 
00367 U32  GUI_X_GetTaskId(void) {
00368     return (U32)Thread::gettid();
00369 }
00370 
00371 void GUI_X_WaitEvent(void) {
00372     Thread::signal_wait(EMWIN_TASK_SIGNAL); //wait forever
00373 }
00374 
00375 void GUI_X_SignalEvent(void) {
00376     if (_emTask) {
00377         osSignalSet(_emTask, EMWIN_TASK_SIGNAL);
00378     }
00379 }
00380 
00381 void GUI_X_WaitEventTimed(int Period) {
00382     static RtosTimer _emTim(emTimeout, osTimerOnce);
00383     if (Period > 0) {
00384         
00385         //wait no more than Period milliseconds
00386         _emTim.start(Period);
00387         Thread::signal_wait(EMWIN_TASK_SIGNAL);
00388         _emTim.stop();
00389     }
00390 }
00391 
00392 /*********************************************************************
00393  *
00394  *      Logging: OS dependent
00395 
00396 Note:
00397   Logging is used in higher debug levels only. The typical target
00398   build does not use logging and does therefor not require any of
00399   the logging routines below. For a release build without logging
00400   the routines below may be eliminated to save some space.
00401   (If the linker is not function aware and eliminates unreferenced
00402   functions automatically)
00403 
00404  */
00405 
00406 void GUI_X_Log     (const char *s) { DMBoard::instance().logger()->printf("emWin[Log] %s\n", s); }
00407 void GUI_X_Warn    (const char *s) { DMBoard::instance().logger()->printf("emWin[Log] %s\n", s); }
00408 void GUI_X_ErrorOut(const char *s) { DMBoard::instance().logger()->printf("emWin[Log] %s\n", s); }
00409 
00410 
00411 
00412 /*********************************************************************
00413  *
00414  *       GUI_TOUCH_X_ActivateX()
00415  *
00416  * Function decription:
00417  *   Called from GUI, if touch support is enabled.
00418  *   Switches on voltage on X-axis,
00419  *   prepares measurement for Y-axis.
00420  *   Voltage on Y-axis is switched off.
00421  */
00422 void GUI_TOUCH_X_ActivateX(void) {
00423 }
00424 
00425 /*********************************************************************
00426  *
00427  *       GUI_TOUCH_X_ActivateY()
00428  *
00429  * Function decription:
00430  *   Called from GUI, if touch support is enabled.
00431  *   Switches on voltage on Y-axis,
00432  *   prepares measurement for X-axis.
00433  *   Voltage on X-axis is switched off.
00434  */
00435 void GUI_TOUCH_X_ActivateY(void) {
00436 }
00437 
00438 /*********************************************************************
00439  *
00440  *       GUI_TOUCH_X_MeasureX()
00441  *
00442  * Function decription:
00443  *   Called from GUI, if touch support is enabled.
00444  *   Measures voltage of X-axis.
00445  */
00446 int  GUI_TOUCH_X_MeasureX(void) {
00447     if (_hal == NULL) return 0;
00448 
00449     return _hal->getTouchX();
00450 }
00451 
00452 /*********************************************************************
00453  *
00454  *       GUI_TOUCH_X_MeasureY()
00455  *
00456  * Function decription:
00457  *   Called from GUI, if touch support is enabled.
00458  *   Measures voltage of Y-axis.
00459  */
00460 int  GUI_TOUCH_X_MeasureY(void) {
00461     if (_hal == NULL) return 0;
00462 
00463     return _hal->getTouchY();
00464 }
00465 
00466 
00467 
00468