Support for the emWin GUI library from Segger.
Dependents: lpc4088_displaymodule_emwin
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
Generated on Sat Jul 16 2022 18:52:19 by 1.7.2