526 lines
19 KiB
C
526 lines
19 KiB
C
/*******************************************************************************
|
|
*
|
|
* E M B E D D E D W I Z A R D P R O J E C T
|
|
*
|
|
* Copyright (c) TARA Systems GmbH
|
|
* written by Paul Banach and Manfred Schweyer
|
|
*
|
|
********************************************************************************
|
|
*
|
|
* This software is delivered "as is" and shows the usage of other software
|
|
* components. It is provided as an example software which is intended to be
|
|
* modified and extended according to particular requirements.
|
|
*
|
|
* TARA Systems hereby disclaims all warranties and conditions with regard to the
|
|
* software, including all implied warranties and conditions of merchantability
|
|
* and non-infringement of any third party IPR or other rights which may result
|
|
* from the use or the inability to use the software.
|
|
*
|
|
********************************************************************************
|
|
*
|
|
* DESCRIPTION:
|
|
* This file implements a generic framework for running Embedded Wizard
|
|
* generated GUI applications on a dedicated target with or without the usage
|
|
* of an operating system.
|
|
* The module ewmain contains three major functions that are used within
|
|
* every Embedded Wizard GUI application: EwInit() - EwProcess() - EwDone().
|
|
* These functions represent the lifecycle of the entire GUI application.
|
|
*
|
|
* EwInit() is responsible to initialize the system, to configure the display,
|
|
* to get access to the desired input devices (like keyboard or touch),
|
|
* to initialize the Embedded Wizard Runtime Environment / Graphics Engine,
|
|
* to create an instance of the application class and to initialize all
|
|
* needed peripheral components.
|
|
*
|
|
* EwProcess() implements one cycle of the main loop. This function has to be
|
|
* called in an (endless) loop and contains typically the following steps:
|
|
* 1. Processing data from your device driver(s)
|
|
* 2. Processing key events
|
|
* 3. Processing cursor or touch screen events
|
|
* 4. Processing timers
|
|
* 5. Processing signals
|
|
* 6. Updating the screen
|
|
* 7. Triggering the garbage collection
|
|
*
|
|
* EwDone() is responsible to shutdown the application and to release all
|
|
* used resources.
|
|
*
|
|
* Important: Please be aware that every Embedded Wizard GUI application
|
|
* requires the execution in a single GUI task!
|
|
* If you are working with an operating system and your software is using
|
|
* several threads/tasks, please take care to access your GUI application
|
|
* only within the context of your GUI thread/task. Use operating system
|
|
* services to exchange data or events between the GUI thread/task and other
|
|
* worker threads/tasks.
|
|
*
|
|
* In order to keep this framework independent from the particular GUI
|
|
* application, the application class and the screen size are taken from the
|
|
* generated code. In this manner, it is not necessary to modify this file
|
|
* when creating new GUI applications. Just set the attributes 'ScreenSize'
|
|
* and 'ApplicationClass' of the profile in the Embedded Wizard IDE.
|
|
*
|
|
* For more information concerning the integration of an Embedded Wizard
|
|
* generated GUI application into your main application, please see
|
|
* https://doc.embedded-wizard.de/main-loop
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#include "ewconfig.h"
|
|
#include "ewmain.h"
|
|
#include "Core.h"
|
|
#include "Graphics.h"
|
|
|
|
#include "ew_bsp_clock.h"
|
|
#include "ew_bsp_event.h"
|
|
#include "ew_bsp_display.h"
|
|
#include "ew_bsp_touch.h"
|
|
|
|
#include "DeviceDriver.h"
|
|
|
|
|
|
/* memory pool */
|
|
#ifdef EW_MEMORY_POOL_SECTION
|
|
EW_MEMORY_POOL_SECTION static unsigned long
|
|
EwMemory[ EW_MEMORY_POOL_SIZE / sizeof( unsigned long )];
|
|
#define EW_MEMORY_POOL_ADDR EwMemory
|
|
#endif
|
|
|
|
/* optional second memory pool */
|
|
#ifdef EW_EXTRA_POOL_SECTION
|
|
EW_EXTRA_POOL_SECTION static unsigned long
|
|
EwExtraMemory[ EW_EXTRA_POOL_SIZE / sizeof( unsigned long )];
|
|
#define EW_EXTRA_POOL_ADDR EwExtraMemory
|
|
#endif
|
|
|
|
#define CHECK_HANDLE( handle ) \
|
|
if ( !handle ) \
|
|
{ \
|
|
EwPrint( "[failed]\n" ); \
|
|
return 0; \
|
|
} \
|
|
else \
|
|
EwPrint( "[OK]\n" );
|
|
|
|
/* helper functions used within this module */
|
|
static void EwUpdate( XViewport* aViewport, CoreRoot aApplication );
|
|
static XEnum EwGetKeyCommand( void );
|
|
|
|
static CoreRoot RootObject;
|
|
static XViewport* Viewport;
|
|
static XDisplayInfo DisplayInfo;
|
|
|
|
|
|
/*******************************************************************************
|
|
* FUNCTION:
|
|
* EwInit
|
|
*
|
|
* DESCRIPTION:
|
|
* EwInit() is responsible to initialize the system, to configure the display,
|
|
* to get access to the desired input devices (like keyboard or touch),
|
|
* to initialize the Embedded Wizard Runtime Environment / Graphics Engine,
|
|
* to create an instance of the application class and to initialize all
|
|
* needed peripheral components.
|
|
*
|
|
* ARGUMENTS:
|
|
* None
|
|
*
|
|
* RETURN VALUE:
|
|
* 1 if successful, 0 otherwise.
|
|
*
|
|
*******************************************************************************/
|
|
int EwInit( void )
|
|
{
|
|
/* initalize system clocks */
|
|
EwBspClockInit();
|
|
|
|
/* set RTC, if current RTC time is before the minimum time */
|
|
if ( EwBspClockGetTime() < RTC_MINIMUM_TIME )
|
|
EwBspClockSetTime( RTC_DEFAULT_TIME );
|
|
|
|
/* initialize display */
|
|
EwPrint( "Initialize Display... " );
|
|
CHECK_HANDLE( EwBspDisplayInit( &DisplayInfo ));
|
|
|
|
/* initialize touchscreen */
|
|
EwPrint( "Initialize Touch Driver... " );
|
|
EwBspTouchInit( DisplayInfo.DisplayWidth, DisplayInfo.DisplayHeight );
|
|
EwPrint( "[OK]\n" );
|
|
|
|
#if EW_MEMORY_POOL_SIZE > 0
|
|
/* initialize heap manager */
|
|
EwPrint( "Initialize Memory Manager... " );
|
|
EwInitHeap( 0 );
|
|
EwAddHeapMemoryPool( (void*)EW_MEMORY_POOL_ADDR, EW_MEMORY_POOL_SIZE );
|
|
|
|
#if EW_EXTRA_POOL_SIZE > 0
|
|
EwAddHeapMemoryPool( (void*)EW_EXTRA_POOL_ADDR, EW_EXTRA_POOL_SIZE );
|
|
#endif
|
|
|
|
EwPrint( "[OK]\n" );
|
|
#endif
|
|
|
|
/* initialize the Graphics Engine and Runtime Environment */
|
|
EwPrint( "Initialize Graphics Engine... " );
|
|
CHECK_HANDLE( EwInitGraphicsEngine( 0 ));
|
|
|
|
/* create the applications root object ... */
|
|
EwPrint( "Create Embedded Wizard Root Object... " );
|
|
RootObject = (CoreRoot)EwNewObjectIndirect( EwApplicationClass, 0 );
|
|
CHECK_HANDLE( RootObject );
|
|
|
|
EwLockObject( RootObject );
|
|
CoreRoot__Initialize( RootObject, EwScreenSize );
|
|
|
|
/* create Embedded Wizard viewport object to provide uniform access to the framebuffer */
|
|
EwPrint( "Create Embedded Wizard Viewport... " );
|
|
Viewport = EwInitViewport( EwScreenSize, EwNewRect( 0, 0, DisplayInfo.BufferWidth, DisplayInfo.BufferHeight ),
|
|
0, 255, DisplayInfo.FrameBuffer, DisplayInfo.DoubleBuffer, 0, 0 );
|
|
CHECK_HANDLE( Viewport );
|
|
|
|
/* initialize your device driver(s) that provide data for your GUI */
|
|
DeviceDriver_Initialize();
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
* FUNCTION:
|
|
* EwDone
|
|
*
|
|
* DESCRIPTION:
|
|
* EwDone() is responsible to shutdown the application and to release all
|
|
* used resources.
|
|
*
|
|
* ARGUMENTS:
|
|
* None
|
|
*
|
|
* RETURN VALUE:
|
|
* None.
|
|
*
|
|
*******************************************************************************/
|
|
void EwDone( void )
|
|
{
|
|
/* deinitialize your device driver(s) */
|
|
DeviceDriver_Deinitialize();
|
|
|
|
/* destroy the applications root object and release unused resources and memory */
|
|
EwPrint( "Shutting down Application... " );
|
|
EwDoneViewport( Viewport );
|
|
EwUnlockObject( RootObject );
|
|
EwReclaimMemory();
|
|
EwPrint( "[OK]\n" );
|
|
|
|
/* deinitialize the Graphics Engine */
|
|
EwPrint( "Deinitialize Graphics Engine... " );
|
|
EwDoneGraphicsEngine();
|
|
EwPrint( "[OK]\n" );
|
|
|
|
#if EW_MEMORY_POOL_SIZE > 0
|
|
/* deinitialize heap manager */
|
|
EwDoneHeap();
|
|
#endif
|
|
|
|
EwPrint( "Deinitialize Touch Driver... " );
|
|
EwBspTouchDone();
|
|
EwPrint( "[OK]\n" );
|
|
|
|
/* deinitialize display */
|
|
EwBspDisplayDone();
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
* FUNCTION:
|
|
* EwProcess
|
|
*
|
|
* DESCRIPTION:
|
|
* EwProcess() implements one cycle of the main loop. This function has to be
|
|
* called in an (endless) loop and contains typically the following steps:
|
|
* 1. Processing data from your device driver(s)
|
|
* 2. Processing key events
|
|
* 3. Processing cursor or touch screen events
|
|
* 4. Processing timers
|
|
* 5. Processing signals
|
|
* 6. Updating the screen
|
|
* 7. Triggering the garbage collection
|
|
* For more information concerning the integration of an Embedded Wizard
|
|
* generated GUI application into your main application, please see
|
|
* https://doc.embedded-wizard.de/main-loop
|
|
*
|
|
* ARGUMENTS:
|
|
* None.
|
|
*
|
|
* RETURN VALUE:
|
|
* 1, if further processing is needed, 0 otherwise.
|
|
*
|
|
*******************************************************************************/
|
|
int EwProcess( void )
|
|
{
|
|
int timers = 0;
|
|
int signals = 0;
|
|
int events = 0;
|
|
int devices = 0;
|
|
XEnum cmd = CoreKeyCodeNoKey;
|
|
int noOfTouch;
|
|
XTouchEvent* touchEvent;
|
|
int touch;
|
|
int finger;
|
|
XPoint touchPos;
|
|
|
|
/* process data of your device driver(s) and update the GUI
|
|
application by setting properties or by triggering events */
|
|
devices = DeviceDriver_ProcessData();
|
|
|
|
/* receive keyboard inputs */
|
|
cmd = EwGetKeyCommand();
|
|
|
|
if ( cmd != CoreKeyCodeNoKey )
|
|
{
|
|
if ( cmd == CoreKeyCodePower )
|
|
return 0;
|
|
|
|
/* feed the application with a 'press' and 'release' event */
|
|
events |= CoreRoot__DriveKeyboardHitting( RootObject, cmd, 0, 1 );
|
|
events |= CoreRoot__DriveKeyboardHitting( RootObject, cmd, 0, 0 );
|
|
}
|
|
|
|
/* receive (multi-) touch inputs and provide it to the application */
|
|
noOfTouch = EwBspTouchGetEvents( &touchEvent );
|
|
|
|
if ( noOfTouch > 0 )
|
|
{
|
|
for ( touch = 0; touch < noOfTouch; touch++ )
|
|
{
|
|
/* get data out of the touch event */
|
|
finger = touchEvent[ touch ].Finger;
|
|
touchPos.X = touchEvent[ touch ].XPos;
|
|
touchPos.Y = touchEvent[ touch ].YPos;
|
|
|
|
/* begin of touch cycle */
|
|
if ( touchEvent[ touch ].State == EW_BSP_TOUCH_DOWN )
|
|
events |= CoreRoot__DriveMultiTouchHitting( RootObject, 1, finger, touchPos );
|
|
|
|
/* movement during touch cycle */
|
|
else if ( touchEvent[ touch ].State == EW_BSP_TOUCH_MOVE )
|
|
events |= CoreRoot__DriveMultiTouchMovement( RootObject, finger, touchPos );
|
|
|
|
/* end of touch cycle */
|
|
else if ( touchEvent[ touch ].State == EW_BSP_TOUCH_UP )
|
|
events |= CoreRoot__DriveMultiTouchHitting( RootObject, 0, finger, touchPos );
|
|
}
|
|
}
|
|
|
|
/* process expired timers */
|
|
timers = EwProcessTimers();
|
|
|
|
/* process the pending signals */
|
|
signals = EwProcessSignals();
|
|
|
|
/* refresh the screen, if something has changed and draw its content */
|
|
if ( devices || timers || signals || events )
|
|
{
|
|
if ( CoreRoot__DoesNeedUpdate( RootObject ))
|
|
EwUpdate( Viewport, RootObject );
|
|
|
|
/* just for debugging purposes: check the memory structure */
|
|
EwVerifyHeap();
|
|
|
|
/* after each processed message start the garbage collection */
|
|
EwReclaimMemory();
|
|
|
|
/* print current memory statistic to console interface */
|
|
#ifdef EW_PRINT_MEMORY_USAGE
|
|
EwPrintProfilerStatistic( 0 );
|
|
#endif
|
|
|
|
/* evaluate memory pools and print report */
|
|
#ifdef EW_DUMP_HEAP
|
|
EwDumpHeap( 0 );
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
/* otherwise sleep/suspend the UI application until a certain event occurs or a timer expires... */
|
|
EwBspEventWait( EwNextTimerExpiration());
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
* FUNCTION:
|
|
* EwUpdate
|
|
*
|
|
* DESCRIPTION:
|
|
* The function EwUpdate performs the screen update of the dirty area.
|
|
*
|
|
* ARGUMENTS:
|
|
* aViewPort - Viewport used for the screen update.
|
|
* aApplication - Root object used for the screen update.
|
|
*
|
|
* RETURN VALUE:
|
|
* None
|
|
*
|
|
*******************************************************************************/
|
|
static void EwUpdate( XViewport* aViewport, CoreRoot aApplication )
|
|
{
|
|
XBitmap* bitmap;
|
|
GraphicsCanvas canvas = EwNewObject( GraphicsCanvas, 0 );
|
|
XRect updateRect = {{ 0, 0 }, { 0, 0 }};
|
|
|
|
if ( !canvas )
|
|
return;
|
|
|
|
if ( DisplayInfo.UpdateMode == EW_BSP_DISPLAY_UPDATE_NORMAL )
|
|
{
|
|
bitmap = EwBeginUpdate( aViewport );
|
|
|
|
/* redraw the dirty area of the screen */
|
|
if ( bitmap )
|
|
{
|
|
GraphicsCanvas__AttachBitmap( canvas, (XHandle)bitmap );
|
|
updateRect = CoreRoot__UpdateGE20( aApplication, canvas );
|
|
GraphicsCanvas__DetachBitmap( canvas );
|
|
EwEndUpdate( aViewport, updateRect );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int regions = CoreRoot__BeginUpdate( aApplication );
|
|
|
|
while ( regions-- )
|
|
{
|
|
/* get rectangular area of the update region for scratch-pad buffer */
|
|
if ( DisplayInfo.UpdateMode == EW_BSP_DISPLAY_UPDATE_SCRATCHPAD )
|
|
updateRect = CoreRoot__GetUpdateRegion( aApplication, regions );
|
|
|
|
/* iterate through all update areas */
|
|
while ( EwBspDisplayGetUpdateArea( &updateRect ))
|
|
{
|
|
/* update the current subarea */
|
|
bitmap = EwBeginUpdateArea( aViewport, updateRect );
|
|
GraphicsCanvas__AttachBitmap( canvas, (XHandle)bitmap );
|
|
CoreRoot__UpdateCanvas( aApplication, canvas, updateRect.Point1 );
|
|
GraphicsCanvas__DetachBitmap( canvas );
|
|
EwEndUpdate( aViewport, updateRect );
|
|
}
|
|
|
|
if ( DisplayInfo.UpdateMode != EW_BSP_DISPLAY_UPDATE_SCRATCHPAD )
|
|
break;
|
|
}
|
|
CoreRoot__EndUpdate( aApplication );
|
|
}
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
* FUNCTION:
|
|
* EwGetKeyCommand
|
|
*
|
|
* DESCRIPTION:
|
|
* The function EwGetKeyCommand reads the next key code from the console and
|
|
* translates it into an Embedded Wizard key code. The mapping between the key
|
|
* code from the console and the resulting Embedded Wizard key code can be
|
|
* adapted to the needs of your application.
|
|
*
|
|
* ARGUMENTS:
|
|
* None
|
|
*
|
|
* RETURN VALUE:
|
|
* Returns the next EmWi key code or CoreKeyCodeNoKey if no key code available.
|
|
*
|
|
*******************************************************************************/
|
|
static XEnum EwGetKeyCommand( void )
|
|
{
|
|
#if EW_USE_TERMINAL_INPUT == 1
|
|
switch ( EwBspConsoleGetCharacter())
|
|
{
|
|
case 0x65 : EwPrint("Key 'Exit' pressed\n"); return CoreKeyCodeExit;
|
|
case 0x38 : EwPrint("Key 'Up' pressed\n"); return CoreKeyCodeUp;
|
|
case 0x32 : EwPrint("Key 'Down' pressed\n"); return CoreKeyCodeDown;
|
|
case 0x36 : EwPrint("Key 'Right' pressed\n"); return CoreKeyCodeRight;
|
|
case 0x34 : EwPrint("Key 'Left' pressed\n"); return CoreKeyCodeLeft;
|
|
case 0x35 : EwPrint("Key 'OK' pressed\n"); return CoreKeyCodeOk;
|
|
case 0x6D : EwPrint("Key 'Menu' pressed\n"); return CoreKeyCodeMenu;
|
|
case 0x70 : EwPrint("Key 'Power' pressed\n"); return CoreKeyCodePower;
|
|
}
|
|
#endif
|
|
return CoreKeyCodeNoKey;
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
* FUNCTION:
|
|
* EwPrintSystemInfo
|
|
*
|
|
* DESCRIPTION:
|
|
* This function prints system and configuration information - very helpful in
|
|
* case of any support issues.
|
|
*
|
|
* ARGUMENTS:
|
|
* None
|
|
*
|
|
* RETURN VALUE:
|
|
* None
|
|
*
|
|
*******************************************************************************/
|
|
void EwPrintSystemInfo( void )
|
|
{
|
|
EwPrint( "---------------------------------------------\n" );
|
|
EwPrint( "Target system %s \n", PLATFORM_STRING );
|
|
EwPrint( "Color format %s \n", EW_FRAME_BUFFER_COLOR_FORMAT_STRING );
|
|
#if EW_MEMORY_POOL_SIZE > 0
|
|
EwPrint( "MemoryPool address 0x%08X \n", EW_MEMORY_POOL_ADDR );
|
|
EwPrint( "MemoryPool size %u bytes\n", EW_MEMORY_POOL_SIZE );
|
|
#endif
|
|
#if EW_EXTRA_POOL_SIZE > 0
|
|
EwPrint( "ExtraPool address 0x%08X \n", EW_EXTRA_POOL_ADDR );
|
|
EwPrint( "ExtraPool size %u bytes\n", EW_EXTRA_POOL_SIZE );
|
|
#endif
|
|
#if EW_USE_SCRATCHPAD_BUFFER == 1
|
|
EwPrint( "Scratch-pad buffer address 0x%08X \n", DisplayInfo.FrameBuffer );
|
|
EwPrint( "Scratch-pad buffer size %u pixel\n", DisplayInfo.BufferWidth * DisplayInfo.BufferHeight );
|
|
#else
|
|
EwPrint( "Framebuffer address 0x%08X \n", DisplayInfo.FrameBuffer );
|
|
#endif
|
|
#if EW_USE_DOUBLE_BUFFER == 1
|
|
EwPrint( "Doublebuffer address 0x%08X \n", DisplayInfo.DoubleBuffer );
|
|
#endif
|
|
#if EW_USE_OFFSCREEN_BUFFER == 1
|
|
EwPrint( "Off-screen buffer used \n" );
|
|
#endif
|
|
EwPrint( "Framebuffer size %u x %u \n", DisplayInfo.BufferWidth, DisplayInfo.BufferHeight );
|
|
EwPrint( "EwScreenSize %d x %d \n", EwScreenSize.X, EwScreenSize.Y );
|
|
EwPrint( "Graphics accelerator %s \n", GRAPHICS_ACCELERATOR_STRING );
|
|
EwPrint( "Vector graphics support %s \n", VECTOR_GRAPHICS_SUPPORT_STRING );
|
|
EwPrint( "Warp function support %s \n", WARP_FUNCTION_SUPPORT_STRING );
|
|
EwPrint( "Index8 bitmap resource format %s \n", INDEX8_SURFACE_SUPPORT_STRING );
|
|
EwPrint( "RGB565 bitmap resource format %s \n", RGB565_SURFACE_SUPPORT_STRING );
|
|
EwPrint( "Bidirectional text support %s \n", BIDI_TEXT_SUPPORT_STRING );
|
|
EwPrint( "Operating system %s \n", OPERATING_SYSTEM_STRING );
|
|
EwPrint( "External flash device %s \n", EXTERNAL_FLASH_STRING );
|
|
#ifdef EW_BITMAP_PIXEL_SECTION_NAME
|
|
EwPrint( "Linker section for bitmap pixel data %s \n", EW_STRINGIZE( EW_BITMAP_PIXEL_SECTION_NAME ));
|
|
#endif
|
|
#ifdef EW_FONT_PIXEL_SECTION_NAME
|
|
EwPrint( "Linker section for font pixel data %s \n", EW_STRINGIZE( EW_FONT_PIXEL_SECTION_NAME ));
|
|
#endif
|
|
EwPrint( "Toolchain %s \n", TOOLCHAIN_STRING );
|
|
#ifdef COMPILER_VERSION_STRING
|
|
EwPrint( "C-Compiler version %s \n", COMPILER_VERSION_STRING );
|
|
#endif
|
|
// EwPrint( "Build date and time %s, %s \n", __DATE__, __TIME__ ); //Removed to improve testing automation using binary comparison
|
|
EwPrint( "Runtime Environment (RTE) version %u.%02u \n", EW_RTE_VERSION >> 16, EW_RTE_VERSION & 0xFF );
|
|
EwPrint( "Graphics Engine (GFX) version %u.%02u \n", EW_GFX_VERSION >> 16, EW_GFX_VERSION & 0xFF );
|
|
EwPrint( "Max surface cache size %u bytes\n", EW_MAX_SURFACE_CACHE_SIZE );
|
|
EwPrint( "Glyph cache size %u x %u \n", EW_MAX_GLYPH_SURFACE_WIDTH, EW_MAX_GLYPH_SURFACE_HEIGHT );
|
|
EwPrint( "Max issue tasks %u \n", EW_MAX_ISSUE_TASKS );
|
|
EwPrint( "Surface rotation %u \n", EW_SURFACE_ROTATION );
|
|
EwPrint( "---------------------------------------------\n" );
|
|
}
|
|
|
|
|
|
/* msy, mli */
|