/*===========================================================================

FILE: myapp.c - Receive SMS Exercise
===========================================================================*/


/*===============================================================================
INCLUDES AND VARIABLE DEFINITIONS
=============================================================================== */
#include "AEEModGen.h"          // Module interface definitions
#include "AEEAppGen.h"          // Applet interface definitions
#include "AEEShell.h"           // Shell interface definitions
#include "AEEMenu.h"			// Menu interface definitions
#include "AEEText.h"            // Text interface definitions
#include "AEEFile.h"			// File interface definitions
#include "AEEGraphics.h"		// Graphics interface definitions
#include "AEEImage.h"			// Image interface definitions
#include "AEEMediaUtil.h"		// Sound Interface definitions
#include "AEETapi.h"			// TAPI interface definitions
#include "AEEStdLib.h"          // Helper functions

#include "myapp.bid"
#include "myapp.brh"

typedef enum {
	APP_STATE_MAIN,
	APP_STATE_FLASH,
	APP_STATE_READ_FILE,
	APP_STATE_RANDOM_LINES,
	APP_STATE_ANIMATION,
	APP_STATE_PLAY_MUSIC,
	APP_STATE_RECEIVE_SMS
} EAppStateType;


/*-------------------------------------------------------------------
Applet structure. All variables in here are reference via "pMe->"
-------------------------------------------------------------------*/
// create an applet structure that's passed around. All variables in
// here will be able to be referenced as static.
typedef struct _myapp {
	AEEApplet      a ;	       // First element of this structure must be AEEApplet
    AEEDeviceInfo  DeviceInfo; // always have access to the hardware device information
    IDisplay      *pIDisplay;  // give a standard way to access the Display interface
    IShell        *pIShell;    // give a standard way to access the Shell interface

    // add your own variables here...
	EAppStateType eAppState;		// Menu application state
	AECHAR UniCodeString[50];       // string buffer
	boolean       flag;			    // toggle flag for flashing
	int           counter;		    // for Drawing Random Lines
	IMenuCtl	  *pIMenu;		    // points to Menu
	IFileMgr	  *pIFileMgr;		// File Mgr Interface
	IFile		  *pIFile;			// File Interface
	IStatic		  *pIStatic;		// Static Interface
	IGraphics	  *pIGraphics;		// Graphics Interface
	IImage		  *pIImage;			// Image Interface
	IMediaUtil    *pIMediaUtil;		// access IMediaUtil interface
	IMedia		  *pIMedia;			// access IMedia interface
	ITAPI         *pITapi;			// ITAPI Interface

} myapp;

/*-------------------------------------------------------------------
Function Prototypes
-------------------------------------------------------------------*/
static  boolean myapp_HandleEvent(myapp* pMe, AEEEvent eCode, 
                                             uint16 wParam, uint32 dwParam);
boolean myapp_InitAppData(myapp* pMe);
void    myapp_FreeAppData(myapp* pMe);
void DisplayResString(myapp *pMe, int16 text);
void DisplayText(myapp *pMe, const AECHAR *string);
void DisplayFlashText(myapp *pMe);
void TimerCB(myapp *pMe);
void DisplayMessage(myapp *pMe, const char *pText);
void DisplayMainMenu(myapp *pMe);
void ResetControls(myapp* pMe);
void QuitApplication(myapp* pMe);
void DisplayReadFile(myapp *pMe, const char *filename);
void DrawRandomLines(myapp *pMe);
void PaintScreen(myapp *pMe);
uint8 RandInt(int max);
void ShowAnimation(myapp *pMe);
void PlayMP3(myapp *pMe, char *pTune);
void GetSMSMessage(myapp *pMe, uint32 dwParam);

/*===============================================================================
FUNCTION DEFINITIONS
=============================================================================== */

/*===========================================================================
FUNCTION: AEEClsCreateInstance

DESCRIPTION
	This function is invoked while the app is being loaded. All Modules must provide this 
	function. Ensure to retain the same name and parameters for this function.
	In here, the module must verify the ClassID and then invoke the AEEApplet_New() function
	that has been provided in AEEAppGen.c. 

   After invoking AEEApplet_New(), this function can do app specific initialization. In this
   example, a generic structure is provided so that app developers need not change app specific
   initialization section every time except for a call to IDisplay_InitAppData(). 
   This is done as follows: InitAppData() is called to initialize AppletData 
   instance. It is app developers responsibility to fill-in app data initialization 
   code of InitAppData(). App developer is also responsible to release memory 
   allocated for data contained in AppletData -- this can be done in 
   IDisplay_FreeAppData().

PROTOTYPE:
   int AEEClsCreateInstance(AEECLSID ClsId,IShell * pIShell,IModule * po,void ** ppObj)

PARAMETERS:
	clsID: [in]: Specifies the ClassID of the applet which is being loaded

	pIShell: [in]: Contains pointer to the IShell object. 

	pIModule: pin]: Contains pointer to the IModule object to the current module to which
	this app belongs

	ppObj: [out]: On return, *ppObj must point to a valid IApplet structure. Allocation
	of memory for this structure and initializing the base data members is done by AEEApplet_New().

DEPENDENCIES
  none

RETURN VALUE
  AEE_SUCCESS: If the app needs to be loaded and if AEEApplet_New() invocation was
     successful
  EFAILED: If the app does not need to be loaded or if errors occurred in 
     AEEApplet_New(). If this function returns FALSE, the app will not be loaded.

SIDE EFFECTS
  none
===========================================================================*/
int AEEClsCreateInstance(AEECLSID ClsId, IShell *pIShell, IModule *po, void **ppObj)
{
	*ppObj = NULL;

	if( ClsId == AEECLSID_MYAPP )
	{
		// Create the applet and make room for the applet structure
		if( AEEApplet_New(sizeof(myapp),
                          ClsId,
                          pIShell,
                          po,
                          (IApplet**)ppObj,
                          (AEEHANDLER)myapp_HandleEvent,
                          (PFNFREEAPPDATA)myapp_FreeAppData) ) // the FreeAppData function is called after sending EVT_APP_STOP to the HandleEvent function
                          
		{
			//Initialize applet data, this is called before sending EVT_APP_START
            // to the HandleEvent function
			if(myapp_InitAppData((myapp*)*ppObj))
			{
				//Data initialized successfully
				return(AEE_SUCCESS);
			}
			else
			{
				//Release the applet. This will free the memory allocated for the applet when
				// AEEApplet_New was called.
				IAPPLET_Release((IApplet*)*ppObj);
				return EFAILED;
			}

        } // end AEEApplet_New

    }

	return(EFAILED);
}


/*===========================================================================
FUNCTION SampleAppWizard_HandleEvent

DESCRIPTION
	This is the EventHandler for this app. All events to this app are handled in this
	function. All APPs must supply an Event Handler.

PROTOTYPE:
	boolean SampleAppWizard_HandleEvent(IApplet * pi, AEEEvent eCode, uint16 wParam, uint32 dwParam)

PARAMETERS:
	pi: Pointer to the AEEApplet structure. This structure contains information specific
	to this applet. It was initialized during the AEEClsCreateInstance() function.

	ecode: Specifies the Event sent to this applet

   wParam, dwParam: Event specific data.

DEPENDENCIES
  none

RETURN VALUE
  TRUE: If the app has processed the event
  FALSE: If the app did not process the event

SIDE EFFECTS
  none
===========================================================================*/
static boolean myapp_HandleEvent(myapp* pMe, AEEEvent eCode, uint16 wParam, uint32 dwParam)
{  

    switch (eCode) 
	{
        // App is told it is starting up
        case EVT_APP_START:                        
		    // Add your code here...
			DisplayMainMenu(pMe);

            return(TRUE);


        // App is told it is exiting
        case EVT_APP_STOP:
            // Add your code here...

      		return(TRUE);


        // App is being suspended 
        case EVT_APP_SUSPEND:
		    // Add your code here...

      		return(TRUE);


        // App is being resumed
        case EVT_APP_RESUME:
		    // Add your code here...
			
      		return(TRUE);


        // An SMS message has arrived for this app. Message is in the dwParam above as (char *)
        // sender simply uses this format "//BREW:ClassId:Message", example //BREW:0x00000001:Hello World
        case EVT_APP_MESSAGE:
		    // Add your code here...
			GetSMSMessage(pMe, dwParam);	   // receive SMS message

      		return(TRUE);

		case EVT_COMMAND:
		{
			// Handle SELECT button events
			switch (wParam) {
				case IDS_FLASH_TEXT:
					DisplayFlashText(pMe);
					return(TRUE);
				case IDS_READ_FILE:
					DisplayReadFile(pMe, "news.txt");
					return(TRUE);
				case IDS_RANDOM_LINES:
					DrawRandomLines(pMe);
					return(TRUE);
				case IDS_ANIMATION:
					ShowAnimation(pMe);
					return(TRUE);
				case IDS_PLAY_MUSIC:
					PlayMP3(pMe, "sample.mp3");
					return(TRUE);
				case IDS_QUIT:
					QuitApplication(pMe);
					return(TRUE);
				
			}
			return(TRUE);
		}

        // A key was pressed. Look at the wParam above to see which key was pressed. The key
        // codes are in AEEVCodes.h. Example "AVK_1" means that the "1" key was pressed.
        case EVT_KEY:
		    // Add your code here...

			// cancel timer
			ISHELL_CancelTimer(pMe->pIShell, NULL, pMe);

			// stop animated image
			IIMAGE_Stop(pMe->pIImage);

			// stop playing music
			if (pMe->pIMedia != NULL) {
				IMEDIA_Stop(pMe->pIMedia);
				IMEDIA_Release(pMe->pIMedia);   // release the interface
				pMe->pIMedia = NULL;
			}

			// let BREW scroll the menu by calling the menu's handler
			if (pMe->pIMenu && IMENUCTL_HandleEvent(pMe->pIMenu, eCode, wParam, dwParam))
					return(TRUE);

			// let BREW scroll the Text Box by calling the Text Box's handler
			// disable keys for scrolling
			if (pMe->pIStatic && (wParam < AVK_1 || wParam > AVK_9) && 
				ISTATIC_HandleEvent(pMe->pIStatic, eCode, wParam, dwParam))
					return TRUE;

			switch (wParam) {
				case AVK_1:					// flash text on display
					DisplayFlashText(pMe);
					break;

				case AVK_2:					// display menu if 2 key was pressed
					// make the Menu active and redraw
					IMENUCTL_SetActive(pMe->pIMenu, TRUE);
					break;

				case AVK_CLR:
					switch (pMe->eAppState) {
						case APP_STATE_FLASH:
						case APP_STATE_READ_FILE:
						case APP_STATE_RANDOM_LINES:
						case APP_STATE_ANIMATION:
						case APP_STATE_PLAY_MUSIC:
						case APP_STATE_RECEIVE_SMS:
							DisplayMainMenu(pMe);
							return TRUE;
						default:
							return FALSE;
					}
					break;
			}

      		return(TRUE);

		// low power mode
		case EVT_APP_NO_SLEEP:
			return(TRUE);

        // If nothing fits up to this point then we'll just break out
        default:
            break;
   }

   return FALSE;
}


// this function is called when your application is starting up
boolean myapp_InitAppData(myapp* pMe)
{
    // Get the device information for this handset.
    // Reference all the data by looking at the pMe->DeviceInfo structure
    // Check the API reference guide for all the handy device info you can get
    pMe->DeviceInfo.wStructSize = sizeof(pMe->DeviceInfo);
    ISHELL_GetDeviceInfo(pMe->a.m_pIShell,&pMe->DeviceInfo);

    // The display and shell interfaces are always created by
    // default, so we'll asign them so that you can access
    // them via the standard "pMe->" without the "a."
    pMe->pIDisplay = pMe->a.m_pIDisplay;
    pMe->pIShell   = pMe->a.m_pIShell;

    // Insert your code here for initializing or allocating resources...
	// Vertical Menu
	if (ISHELL_CreateInstance(pMe->pIShell, AEECLSID_MENUCTL, 
								(void **)&pMe->pIMenu) != SUCCESS) {
		pMe->pIMenu = NULL;
		return FALSE;
	}
	// open File Manager
	if (ISHELL_CreateInstance(pMe->pIShell, AEECLSID_FILEMGR, 
								(void **)&pMe->pIFileMgr) != SUCCESS) {
		pMe->pIFileMgr = NULL;
		return FALSE;
	}
	// open Static Text Box Library
	if (ISHELL_CreateInstance(pMe->pIShell, AEECLSID_STATIC, 
								(void **)&pMe->pIStatic) != SUCCESS) {
		pMe->pIStatic = NULL;
		return FALSE;
	}
	// open Graphics Library
	if (ISHELL_CreateInstance(pMe->pIShell, AEECLSID_GRAPHICS, 
								(void **)&pMe->pIGraphics) != SUCCESS) {
		pMe->pIGraphics = NULL;
		return FALSE;
	}
	// load animated image "dog.bci"
	if ((pMe->pIImage = ISHELL_LoadImage(pMe->pIShell, "dog.bci")) == NULL)
		return FALSE;

	// open IMedia Library
	if (ISHELL_CreateInstance(pMe->pIShell, AEECLSID_MEDIAUTIL, 
								(void **)&pMe->pIMediaUtil) != SUCCESS) {
		pMe->pIMediaUtil = NULL;
		return FALSE;
	}
	// open ITapi Library
	if (ISHELL_CreateInstance(pMe->pIShell, AEECLSID_TAPI, 
								(void **)&pMe->pITapi) != SUCCESS) {
		pMe->pITapi = NULL;
		return FALSE;
	}
	pMe->flag = TRUE;
	pMe->counter = 0;

    // if there have been no failures up to this point then return success
    return TRUE;
}

// this function is called when your application is exiting
void myapp_FreeAppData(myapp* pMe)
{
    // insert your code here for freeing any resources you have allocated...
	if (pMe->pIMenu != NULL) {           // check for NULL first
        IMENUCTL_Release(pMe->pIMenu);   // release the interface
        pMe->pIMenu = NULL;              // set to NULL so no problems trying to free later
    }
	if (pMe->pIFileMgr != NULL) {          // check for NULL first
        IFILEMGR_Release(pMe->pIFileMgr);  // release the interface
        pMe->pIFileMgr = NULL;             // set to NULL so no problems trying to free later
    }
	if (pMe->pIStatic != NULL) {          // check for NULL first
        ISTATIC_Release(pMe->pIStatic);   // release the interface
        pMe->pIStatic = NULL;             // set to NULL so no problems trying to free later
    }
	if (pMe->pIGraphics != NULL) {           // check for NULL first
        IGRAPHICS_Release(pMe->pIGraphics);  // release the interface
        pMe->pIGraphics = NULL;              // set to NULL so no problems trying to free later
    }
	if (pMe->pIImage != NULL) {         // check for NULL first
        IIMAGE_Release(pMe->pIImage);   // release the interface
        pMe->pIImage = NULL;            // set to NULL so no problems trying to free later
    }
	if (pMe->pIMediaUtil != NULL) {        // check for NULL first
        IMEDIAUTIL_Release(pMe->pIMediaUtil);   // release the interface
        pMe->pIMediaUtil = NULL;          // set to NULL so no problems trying to free later
    }
    if (pMe->pIMedia != NULL) {			// check for NULL first
        IMEDIA_Release(pMe->pIMedia);   // release the interface
        pMe->pIMedia = NULL;            // set to NULL so no problems trying to free later
    }
	if (pMe->pITapi != NULL) {		   // check for NULL first
        ITAPI_Release(pMe->pITapi);    // release the interface
        pMe->pITapi = NULL;            // set to NULL so no problems trying to free later
    }
}

/***********************************************************************
   Exercise - Display Resource String
************************************************************************/

void DisplayText(myapp *pMe, const AECHAR *string) {
	IDISPLAY_ClearScreen(pMe->pIDisplay);
	IDISPLAY_DrawText(pMe->pIDisplay,    // Display instance
           AEE_FONT_BOLD,       // Use BOLD font
           string,				// Text - Normally comes from resource
           -1,                  // -1 = Use full string length
           0,                   // Ignored - IDF_ALIGN_CENTER
           0,                   // Ignored - IDF_ALIGN_MIDDLE
           NULL,                // No clipping
           IDF_ALIGN_CENTER | IDF_ALIGN_MIDDLE);

	// Update Screen Display
     IDISPLAY_Update(pMe->pIDisplay);
}

void DisplayResString(myapp *pMe, int16 text) {
	ISHELL_LoadResString(pMe->pIShell,
					MYAPP_RES_FILE,
					text,
					pMe->UniCodeString,
					sizeof(pMe->UniCodeString));
	DisplayText(pMe, pMe->UniCodeString);
}

void DisplayMessage(myapp *pMe, const char *pText) {
	DisplayText(pMe, STRTOWSTR(pText, pMe->UniCodeString, 
		sizeof(pMe->UniCodeString)));
}

void DisplayFlashText(myapp* pMe) {
	ResetControls(pMe);
	DisplayResString(pMe, IDS_HELLO);
	ISHELL_SetTimer(pMe->pIShell, 200, (PFNNOTIFY)TimerCB, pMe);
	pMe->eAppState = APP_STATE_FLASH;
}

/***********************************************************************
   Exercise - Flashing Timer
************************************************************************/

void TimerCB(myapp *pMe) {
	if (pMe->flag)
		// Display string on the screen
		DisplayText(pMe, pMe->UniCodeString);
	else {
		// Clear the display.
		IDISPLAY_ClearScreen(pMe->pIDisplay);
		IDISPLAY_Update(pMe->pIDisplay);
	}
	// start up timer again
	ISHELL_SetTimer(pMe->pIShell, 200, (PFNNOTIFY)TimerCB, pMe);
	pMe->flag = (pMe->flag ? FALSE : TRUE);
}

/***********************************************************************
   Exercise - Menu Selections
************************************************************************/

void DisplayMainMenu(myapp* pMe) 
{
	ResetControls(pMe);
	// load Main Menu items only after startup
	IMENUCTL_SetTitle(pMe->pIMenu, MYAPP_RES_FILE, IDS_MAIN_MENU, NULL);
	IMENUCTL_AddItem(pMe->pIMenu, MYAPP_RES_FILE, IDS_FLASH_TEXT, 
									IDS_FLASH_TEXT, NULL, IDS_FLASH_TEXT);
	IMENUCTL_AddItem(pMe->pIMenu, MYAPP_RES_FILE, IDS_READ_FILE, 
									IDS_READ_FILE, NULL, IDS_READ_FILE);
	IMENUCTL_AddItem(pMe->pIMenu, MYAPP_RES_FILE, IDS_RANDOM_LINES, 
									IDS_RANDOM_LINES, NULL, IDS_RANDOM_LINES);
	IMENUCTL_AddItem(pMe->pIMenu, MYAPP_RES_FILE, IDS_ANIMATION, 
									IDS_ANIMATION, NULL, IDS_ANIMATION);
	IMENUCTL_AddItem(pMe->pIMenu, MYAPP_RES_FILE, IDS_PLAY_MUSIC, 
									IDS_PLAY_MUSIC, NULL, IDS_PLAY_MUSIC);
	IMENUCTL_AddItem(pMe->pIMenu, MYAPP_RES_FILE, IDS_QUIT, IDS_QUIT, NULL, IDS_QUIT);
	IMENUCTL_SetActive(pMe->pIMenu, TRUE);
	pMe->eAppState = APP_STATE_MAIN;
}

void ResetControls(myapp* pMe)
{
	// Make Menu Control inactive
	IMENUCTL_SetActive(pMe->pIMenu, FALSE);

	// Make Static Control inactive
	ISTATIC_SetActive(pMe->pIStatic, FALSE);

	// cancel timer
	ISHELL_CancelTimer(pMe->pIShell, NULL, pMe);

	// stop animated image
	IIMAGE_Stop(pMe->pIImage);

	// stop playing music
	if (pMe->pIMedia != NULL)
		IMEDIA_Stop(pMe->pIMedia);

    // Clear Screen
    IDISPLAY_ClearScreen(pMe->pIDisplay);
	IDISPLAY_Update(pMe->pIDisplay);
}

void QuitApplication(myapp* pMe) {
	ISHELL_CloseApplet(pMe->pIShell, FALSE);
}

/***********************************************************************
   Exercise - Read Text File
************************************************************************/

void DisplayReadFile(myapp *pMe, const char *filename) {
	ResetControls(pMe);

	// open  file
	pMe->pIFile = IFILEMGR_OpenFile(pMe->pIFileMgr, filename, _OFM_READ);

	// make sure the open succeeds
	if (pMe->pIFile != NULL) {
		FileInfo file_info;  char *stBuffer;

		// Get size of File and allocate memory
		IFILE_GetInfo(pMe->pIFile, &file_info);
		stBuffer = MALLOC(file_info.dwSize+1);
		stBuffer[file_info.dwSize] = '\0';

		// read the data
		IFILE_Read(pMe->pIFile, stBuffer, file_info.dwSize);
		IFILE_Release(pMe->pIFile);			// close the file

		// tell window that data is ASCII, no auto scrolling
		ISTATIC_SetProperties(pMe->pIStatic, ST_ASCII | ST_NOSCROLL);
		 // load text into static text window
		ISTATIC_SetText(pMe->pIStatic, NULL, 
					(AECHAR *)stBuffer, AEE_FONT_NORMAL, AEE_FONT_NORMAL);
		// make the Static Text Box the active window and redraw
		ISTATIC_SetActive(pMe->pIStatic, TRUE);
		ISTATIC_Redraw(pMe->pIStatic);
		FREE(stBuffer);       // free memory for file data
	} else
		DisplayMessage(pMe, "Can't open file");
	pMe->eAppState = APP_STATE_READ_FILE;
}

/***********************************************************************
   Exercise - Graphics Exercise (RandomLines)
************************************************************************/

void DrawRandomLines(myapp *pMe) {
	ResetControls(pMe);
	ISHELL_SetTimer(pMe->pIShell, 50, (PFNNOTIFY)PaintScreen, pMe);
	pMe->eAppState = APP_STATE_RANDOM_LINES;
}

uint8 RandInt(int max) {
	uint8 value;
	GETRAND( (byte *)(&value), sizeof(uint8));
	return value % max;
}

void PaintScreen(myapp *pMe) {
	AEELine Line;		// holds line coordinates

	if (pMe->counter == 100) {
		// clear the display and start over
		IDISPLAY_ClearScreen( pMe->pIDisplay );
		pMe->counter = 0;
	}
	pMe->counter++;

	// set the color to random RGB values
	IGRAPHICS_SetColor(pMe->pIGraphics, 
			RandInt(256), RandInt(256), RandInt(256), 0);

	// set coordinates to random values within screen
	Line.sx = RandInt(pMe->DeviceInfo.cxScreen);
	Line.sy = RandInt(pMe->DeviceInfo.cyScreen);
	Line.ex = RandInt(pMe->DeviceInfo.cxScreen);
	Line.ey = RandInt(pMe->DeviceInfo.cyScreen);

	// draw random line with random color
	IGRAPHICS_DrawLine(pMe->pIGraphics, &Line);

	// update the display screen
	IGRAPHICS_Update(pMe->pIGraphics);

	// set timer to draw again
	ISHELL_SetTimer(pMe->pIShell, 50, (PFNNOTIFY)PaintScreen, pMe);
}

/***********************************************************************
   Exercise - Animation Exercise
************************************************************************/

void ShowAnimation(myapp *pMe) {
	AEEImageInfo imageInfo;
	ResetControls(pMe);

	// start music
	PlayMP3(pMe, "sample.mp3");
    IDISPLAY_ClearScreen(pMe->pIDisplay);
	IDISPLAY_Update(pMe->pIDisplay);

	// get width of screen
	IIMAGE_GetInfo(pMe->pIImage, &imageInfo);
	// start animation
	IIMAGE_Start(pMe->pIImage, pMe->DeviceInfo.cxScreen/2 - imageInfo.cx/2, 0);
	pMe->eAppState = APP_STATE_ANIMATION;
}

/***********************************************************************
   Exercise - Play MP3 Exercise
************************************************************************/

void PlayMP3(myapp *pMe, char *pTune) {
	ResetControls(pMe);

	// make sure the MP3 file is there
	if (IFILEMGR_Test(pMe->pIFileMgr, pTune) == SUCCESS) {
		// create media data structure for MP3
		AEEMediaData MediaData;
		// set media source as buffer in Imedia object
		MediaData.clsData = MMD_FILE_NAME;
		MediaData.pData = pTune;
		// tell media the name of the MP3 to play
		if (IMEDIAUTIL_CreateMedia(pMe->pIMediaUtil, &MediaData, &pMe->pIMedia) == SUCCESS) {
			// start playing the MP3
			DisplayMessage(pMe, "Playing Music");
			IMEDIA_Play(pMe->pIMedia);
		} else
			DisplayMessage(pMe, "Unable to play media");
	} else
		DisplayMessage(pMe, "Can't open MP3 file");
	pMe->eAppState = APP_STATE_PLAY_MUSIC;
}

/***********************************************************************
   Exercise - Receive SMS Exercise
************************************************************************/

void GetSMSMessage(myapp *pMe, uint32 dwParam) {
	char *msg = (char *)dwParam;	  // get SMS message
	ResetControls(pMe);
	DisplayMessage(pMe, msg);
	pMe->eAppState = APP_STATE_RECEIVE_SMS;
}


