Full IPOD Like GUI Demo - MBED + SmartGPU2 board

Dependencies:   SMARTGPU2 mbed

main.cpp

Committer:
emmanuelchio
Date:
2014-04-17
Revision:
1:2845aaa91e22
Parent:
0:9ec50d21947d

File content as of revision 1:2845aaa91e22:

/**************************************************************************************/
/**************************************************************************************/
/*SMARTGPU2 intelligent embedded graphics processor unit
 those examples are for using the SMARTGPU2 with the mbed microcontoller, just connect tx,rx,and reset
 Board:
 http://www.vizictechnologies.com/
 
 www.vizictechnologies.com 
 Vizic Technologies copyright 2014 */
/**************************************************************************************/
/**************************************************************************************/

#include "mbed.h"
#include "SMARTGPU2.h"
#include "stdlib.h"

SMARTGPU2 lcd(TXPIN,RXPIN,RESETPIN);  //create our object called "lcd"

//defines for GUI
#define HALFX 240/2
#define HALFY 320/2

//declare our structures POINT and ICON
POINT point;
ICON icon;
       
//array to store file names 25 characters max, also used as working file array
char name[25];

//Array with the names of the icons under "FullGUI/Ics" folder, names of 25 characters max
#define TOTALICONS  13          //number of available icons, current sketch supports 25 icons max
const char iconNames[TOTALICONS][25]={"backlight","calculator","clock","games","maps","media","notes","photos","wifi","settings","calls","music","wall"};

//array used by games
#define MOLEHOLE 3        //position of the array where mole hole image is contained
#define HITMOLE 4         //position of the array where hit mole image is contained
#define MISSMOLE 5        //position of the array where miss mole image is contained
const char moleType[6][9]={"MoleHap","MoleSee","MoleBad","MoleHole","MolePun","MoleMiss"}; //array containing the names of the different called images    

//General/Miscellaneous Functions
/**************************************************/
/**************************************************/
/**************************************************/
unsigned char getTouchIconMainMenu(void){
  unsigned int icPress;  

  while(lcd.touchScreen(&point)==INVALID);      //wait for a touch  
  //PROCEDURE TO DIVIDE THE TOUCHSCREEN AREA IN 4 x 5 EQUAL PARTS--------------------------------------------
  //Divide screen into 4 equal horizontal parts for icons
  icPress= (point.x/(LCD_HEIGHT/4)) + 1; //LCD_HEIGHT is 240    
  //Divide Screen into 5 equal vertical parts for icons
  icPress = icPress + (((point.y)/(LCD_WIDTH/5)) * 4); //LCD_WIDTH is 320
  //------------------------------------------------------------------------------------------------- 
 return icPress; //return decoded coordinate from 1 to 20
}

//obtain from EEPROM FLASH memory the name of the current stored wallpaper on the "name" array
void getCurrentWallFromEEPROM(void){
  NUMBEROFBYTES bytesRead;
  lcd.fillBuffFromEEPROMPage(PAGE0); //copy PAGE0 to EEPROM RAM buffer
  lcd.readEEPROMBuff(name,0,14,&bytesRead);   //read 14 bytes of the EEPROM RAM buffer to name array, wallpapers must not exceed 14 chars in name lenght
  if(strstr(name, 0x00) != 0x00){    //find a null character in name, if not find, add the 0x00 NULL character
    name[0] = 0x00;
  }
}

//save current contents of "name" array on EEPROM PAGE0 at address 0x0000
void saveWallpaperToEEPROM(void){
  NUMBEROFBYTES bytesWritten;
  lcd.initClearEEPROMBuff();                  //Initialize EEPROM RAM Buffer
  lcd.writeEEPROMBuff(name,0,sizeof(name),&bytesWritten); //write all the contents of "name" array to EEPROM RAM Buffer
  lcd.eraseEEPROMPage(PAGE0);                 //erase all contents on the PAGE0
  lcd.saveBuffToEEPROMPage(PAGE0);            //now save to EEPROM PAGE0 the contents of the EEPROM RAM Buffer(the name array + 0xFFs)
}

/**************************************************/
void drawHeader(char *text){
  NUMBEROFBYTES charsPrinted;
  unsigned int batteryPercentage = 65;  
  //draw header and text
  lcd.drawRectangle(0,0,MAX_X_PORTRAIT,13,BLACK,FILL);  //draw upper bar
  lcd.setTextSize(FONT0);
  lcd.setTextColour(WHITE);
  lcd.setTextBackFill(TRANS);
  lcd.string(2,0,MAX_X_PORTRAIT,20,"Vizic",&charsPrinted);          //draw Vizic string
  lcd.string(85,0,MAX_X_PORTRAIT,20,text,&charsPrinted);            //draw string
  //draw battery icon according to the battery percentage variable
  lcd.drawRectangle(215,0,215+((batteryPercentage*15)/100),10,GREEN,FILL);
  lcd.drawRectangle(215,0,230,10,WHITE,UNFILL);
  lcd.drawRectangle(230,4,232,6,WHITE,FILL);  
}

//Cuts the .ext and updates the name
void cutFileExtension(char *name, char *ext){
  char *pch;
  pch=strstr(name,ext);        //find the .ext extension to the name
  strncpy(pch,0x00,1);         //cut/replace the .ext extension for the NULL 0x00 character      
}

 //This function call the desired image in the position of the desired hole - used by games()
void showMole(char mole, char hole){  
  switch(hole){
    case 1:
      lcd.imageBMPSD(38,70,(char*)moleType[mole]); // hole 1
    break;
    case 2:
      lcd.imageBMPSD(138,70,(char*)moleType[mole]); // hole 2
    break;  
    case 3:
      lcd.imageBMPSD(240,70,(char*)moleType[mole]); // hole 3
    break;    
    case 4:
      lcd.imageBMPSD(38,147,(char*)moleType[mole]); // hole 4
    break;  
    case 5:
      lcd.imageBMPSD(138,147,(char*)moleType[mole]); // hole 5
    break;
    case 6:
      lcd.imageBMPSD(240,147,(char*)moleType[mole]); // hole 6
    break;
    default:
    break;
  } 
}

//This function returns 1 if a touch has been made in a specified hole -used by games
char touchOnHole(char hole){
  char hit=0; 
  switch(hole){
    case 1:
      if(point.x>0 && point.x<111 && point.y>65 && point.y<146) hit=1;   //check if the last touch was inside this area
    break;
    case 2:
      if(point.x>110 && point.x<211 && point.y>65 && point.y<146) hit=1; //check if the last touch was inside this area
    break;  
    case 3:
      if(point.x>210 && point.x<320 && point.y>65 && point.y<146) hit=1; //check if the last touch was inside this area
    break;    
    case 4:
      if(point.x>0 && point.x<111 && point.y>145 && point.y<240) hit=1;  //check if the last touch was inside this area
    break;  
    case 5:
      if(point.x>110 && point.x<211 && point.y>145 && point.y<240) hit=1;//check if the last touch was inside this area
    break;
    case 6:
      if(point.x>210 && point.x<320 && point.y>145 && point.y<240) hit=1;//check if the last touch was inside this area
    break;
    default:
    break;
  }  
  return hit;  
}

 //function used by music
void drawControlRR(ACTIVE state){
  //draw button
  lcd.objButton(0,265,79,315,state,"");
  //draw symbol
  lcd.drawTriangle(0+10,265+((315-265)/2),0+39,265+10,0+39,315-10,BLACK,FILL);
  lcd.drawTriangle(0+39,265+((315-265)/2),0+79-10,265+10,0+79-10,315-10,BLACK,FILL);
}

//function used by music
void drawControlFF(ACTIVE state){
  //draw button  
  lcd.objButton(160,265,MAX_X_PORTRAIT,315,state,"");    
  //draw symbol
  lcd.drawTriangle(160+10,265+10,160+10,315-10,160+39,265+((315-265)/2),BLACK,FILL);  
  lcd.drawTriangle(160+39,265+10,160+39,315-10,239-10,265+((315-265)/2),BLACK,FILL);  
} 

//function used by music
void drawControlPLAY(char symbol){
  //draw button  
  lcd.objButton(80,265,159,315,SELECTED,"");  
  //draw symbol
  if(symbol){      //PLAY
    lcd.drawTriangle(80+10,265+10,80+10,315-10,159-10,265+((315-265)/2),BLACK,FILL);
  }else{           //PAUSE
    lcd.drawRectangle(80+10,265+10,80+10+25,315-10,BLACK,FILL);
    lcd.drawRectangle(159-10-25,265+10,159-10,315-10,BLACK,FILL);
  }
}

//function that draws buttons and current progress bar - used by media
void drawButtonsAndProgress(unsigned long currFrame, unsigned long totFrames){
  lcd.objButton(0,200,159,230,DESELECTED,"Continue");
  lcd.objButton(161,200,MAX_X_LANDSCAPE,230,DESELECTED,"Return...");
  lcd.drawRectangle(0,170,(currFrame*MAX_X_LANDSCAPE)/(totFrames),190,RED,FILL);                 //scale currentFrame value to 0-319 pixels
  lcd.drawRectangle((currFrame*MAX_X_LANDSCAPE)/(totFrames),170,MAX_X_LANDSCAPE,190,BLACK,FILL); //scale currentFrame value to 0-319 pixels 
}

//Main applications, the next applications are called by the main loop menu
/**************************************************/
/**************************************************/
/**************************************************/
//draws Main Menu
void drawMainMenu(void){  
  unsigned int i=0, x=8, y=20;
  SMARTGPUREPLY res;
  char aux[25];

  strcpy(aux,"Wall/");                      //copy to name the string "Wall/"
  getCurrentWallFromEEPROM();                   //fill global "name" array with the current EEPROM Stored name
  strcat(aux,name);                             //concatenate the currentWall name to "Wall/"
  if(lcd.imageBMPSD(0,0,aux)!=OK) lcd.erase();  //try to draw WallPaper Image, if fail, just erase screen
  //now draw all top icons
  lcd.SDFopenDir("Ics");                     //open the folder with the icons
  while(i<TOTALICONS){                       
    res=lcd.imageBMPSD(x,y,(char*)iconNames[i++]);  //try to draw icon and advance i
    if(res == OK){                           //draw icon file, only if command success then advance x and y position
      x+=50+8;                               //advance the icon size 50 + 8 the space between icons
      if(x>230){                             //if x > 230, means we have reach the end of file and must advance 1 coloumn
        x=8;                                 //reset x
        y+=50+10;                            //advance the icon size 50 + 10 the space between icons
        if(y>300) break;                     //if there are more than 20 icons, break and ignore, current sketch supports only 20 icons max
      }
    }
  }
  lcd.SDFopenDir("..");                      //return/go up to parent dir one level
  drawHeader("Main Menu");
  wait_ms(350);                              //A little delay to avoid fast image changing   
}

/**************************************************/
void backlight(void){
  static unsigned char currentBacklightValue=100; //0-100
  NUMBEROFBYTES charsPrinted;
  
  lcd.drawGradientRect(0,0,MAX_X_PORTRAIT,MAX_Y_PORTRAIT,BLACK,MAGENTA,VERTICAL); //draw a fullscreen gradient rectangle
  lcd.setTextSize(FONT3);
  lcd.setTextColour(WHITE);
  lcd.setTextBackFill(TRANS);
  lcd.string(40,45,MAX_X_PORTRAIT,MAX_Y_PORTRAIT,"Brightness Bar",&charsPrinted);
  lcd.objSlider(10,80,MAX_X_PORTRAIT-10,150,currentBacklightValue,101,HORIZONTAL);
  lcd.objButton(10,280,MAX_X_PORTRAIT-10,310,DESELECTED,"Return");
  drawHeader("Adjustments:");  
  while(1){
    while(lcd.touchScreen(&point)==INVALID);//wait for a touch on screen to do something
    if((point.x>10) && (point.x<MAX_X_PORTRAIT-10) && (point.y>80) && (point.y<150)){  //if touch inside brightness bar
      currentBacklightValue= ((point.x-10)*100)/(MAX_X_PORTRAIT-10-10);                //scale obtained touch value to 0-100
      lcd.objSlider(10,80,MAX_X_PORTRAIT-10,150,currentBacklightValue,101,HORIZONTAL); //update slider
      lcd.bright(currentBacklightValue);                                               //set new brightness value
      wait_ms(150);
    }
    if(point.y>280){ //if touch inside return button
      lcd.objButton(10,280,MAX_X_PORTRAIT-10,310,SELECTED,"Return");
      wait_ms(300);
      return; //exit function
    }     
  }
}

/**************************************************/
void clocks(void){
  int hours=4,mins=48,secs=0,i=0;
  int xs,ys,xm,ym,xh,yh;
  int angleH,angleM,angleS;
  int handHour=55;//hand size
  int handMin=70; //hand size
  int handSec=75; //hand size 
  
  lcd.drawGradientRect(0,0,MAX_X_PORTRAIT,MAX_Y_PORTRAIT,BLACK,MAGENTA,VERTICAL); //draw a fullscreen gradient rectangle
  lcd.objButton(10,280,MAX_X_PORTRAIT-10,310,DESELECTED,"Return");
  drawHeader("Clocks:");    
  //drawClock Body
  lcd.drawCircle(HALFX,HALFY,80,BLACK,FILL);
  lcd.drawCircle(HALFX,HALFY,80,WHITE,UNFILL);  
  
  while(1){
    //Do some Math to get the second point of the clock hands. (first point is always the center of the clock)
    angleS=secs*6;                           //get the current seconds in angle form, a circle have 360 degrees divided by 60 seconds = 6, then we multiply the 6 by the current seconds to get current angle
    xs=(sin((angleS*3.14)/180)) * handSec;   //get X component of the second's hand
    ys=(cos((angleS*3.14)/180)) * handSec;   //get Y component of the second's hand
    angleM=mins*6;                           //get the current minutes in angle form, a circle have 360 degrees divided by 60 minutes = 6, then we multiply the 6 by the current minutes to get current angle
    xm=(sin((angleM*3.14)/180)) * handMin;   //get X component of the minutes's hand
    ym=(cos((angleM*3.14)/180)) * handMin;   //get Y component of the minutes's hand 
    angleH=hours*30;                         //get the current hours in angle form, a circle have 360 degrees divided by 12 hours = 30, then we multiply the 30 by the current hours to get current angle
    xh=(sin((angleH*3.14)/180)) * handHour;  //get X component of the hours's hand
    yh=(cos((angleH*3.14)/180)) * handHour;  //get Y component of the hours's hand
     
    //Draw current time hands  
    lcd.drawLine(HALFX,HALFY,HALFX+xm,HALFY-ym,WHITE); // Draw the minutes hand, first point is the center of the clock, and the second is the point obtained by doing math
    lcd.drawLine(HALFX,HALFY,HALFX+xh,HALFY-yh,WHITE); // Draw the hours hand, first point is the center of the clock, and the second is the point obtained by doing math
    lcd.drawLine(HALFX,HALFY,HALFX+xs,HALFY-ys,RED);   // Draw the seconds hand, first point is the center of the clock, and the second is the point obtained by doing math
    lcd.drawCircle(HALFX,HALFY,3,RED,FILL);            // Draw the center of the second's hand
 
    for(i=0;i<10;i++){                                 //loop for 10 times a delay of 100ms asking for a touch - this gives a total delay of 1 second
      if(lcd.touchScreen(&point)==VALID){ //ask for a touch on screen to do something
        if(point.y>280){ //if touch inside return button
          lcd.objButton(10,280,MAX_X_PORTRAIT-10,310,SELECTED,"Return");
          wait_ms(300);
          return; //exit function
        }    
      }
      wait_ms(100);
    }
  
    //time managing
    secs++;                                         // increase seconds
    if(secs==60){                                   // if we reach 60 seconds
      mins++;                                       // increase the minutes
      if(mins==60){                                 // if we reach 60 minutes
        hours++;                                    // increase the minutes
        if(hours==12){                              // if we reach 12 hours
          hours=0;                                  // clear hours
        } 
        mins=0;                                     // clear minutes
      }            
      secs=0;                                       // clear seconds
    }                      
    //Erase all hands         
    lcd.drawLine(HALFX,HALFY,HALFX+xs,HALFY-ys,BLACK); // Erase Second's hand
    lcd.drawLine(HALFX,HALFY,HALFX+xm,HALFY-ym,BLACK); // Erase Minute's hand
    lcd.drawLine(HALFX,HALFY,HALFX+xh,HALFY-yh,BLACK); // Erase Hour's hand            
  } 
}  

/**************************************************/
void photos(void){
  unsigned int dirs=0,pics=0;
  static unsigned int i=0;           //static to save last image position even we exit function
  NUMBEROFBYTES charsPrinted;
  
  lcd.orientation(LANDSCAPE_LEFT);  //set orientation as landscape
  lcd.setTextColour(WHITE);
  lcd.setTextSize(FONT3);
  lcd.setTextBackFill(TRANS);
  lcd.drawGradientRect(0,0,MAX_X_LANDSCAPE,MAX_Y_LANDSCAPE,BLACK,MAGENTA,VERTICAL);
  lcd.string(80,110,MAX_X_LANDSCAPE,MAX_Y_LANDSCAPE,"Photo Gallery",&charsPrinted);
  lcd.setTextSize(FONT2);  
  wait_ms(1000);
  lcd.SDFopenDir("Photos");          //open the folder with the photos
  lcd.SDFgetList(&dirs,&pics);           //get number of files/Pics under the current folder "Photos"
  
  while(1){  
    lcd.SDFgetFileName(i,name);                        //get the name of the pic file number i
    cutFileExtension(name,".bmp");                     //cut to name the .bmp extension
    lcd.imageBMPSD(0,0,name);                          //Load image from SD card, all images are 320x240(full screen) so we load them from top left corner X:0,Y:0
    wait_ms(200);                                      //A little delay to avoid fast image changing    
    lcd.string(60,220,319,239,"<Tap center to Exit>",&charsPrinted); //Show text
    while(lcd.touchScreen(&point)==INVALID);           //wait for a touch to do something    
    //check if we go to the next image, or to the previous one
    if(point.x>219){                                   //if the received touch was on the right corner of the screen we advance the image, else we decrease and go to previous image
      i++;                                             //decrease image selector
      if(i>=pics){                                     //if we reach the position of the last image, we restart to image 0
        i=0;                 
      }        
    }
    else if(point.x<100){
      if(i>0){                                         //if we can decrease i
        i--;    
      }else{                                           //if we decrease i will be less than zero, so we move to last image instead
        i=pics-1;  
      }
    }
    else{                                              //touch on center, EXIT      
      break;
    }   
  }
  lcd.SDFopenDir("..");                                //return/go up to parent dir one level
  lcd.orientation(PORTRAIT_LOW);                       //change to portrait mode    
  wait_ms(300);
}

/**************************************************/
void media(){
  unsigned int i=0, row=0, vids=0;
  unsigned long currentFrame=0, currentSecond=0;
  VIDDATA videoData;
  NUMBEROFBYTES charsPrinted;
  
  lcd.orientation(LANDSCAPE_LEFT);   //set orientation as landscape
  lcd.setTextColour(WHITE);
  lcd.setTextSize(FONT3);
  lcd.setTextBackFill(TRANS);
  lcd.drawGradientRect(0,0,MAX_X_LANDSCAPE,MAX_Y_LANDSCAPE,BLACK,MAGENTA,VERTICAL);
  lcd.string(80,110,MAX_X_LANDSCAPE,MAX_Y_LANDSCAPE,"Video Player",&charsPrinted);
  lcd.stopWAVFile();                 //stop current playing song if any   
  wait_ms(1000);
  lcd.SDFopenDir("Videos");          //open the folder with the videos
  lcd.setTextSize(FONT2);

  while(1){
    lcd.drawGradientRect(0,0,MAX_X_LANDSCAPE,MAX_Y_LANDSCAPE,BLACK,MAGENTA,VERTICAL);
    lcd.string(5,0,MAX_X_LANDSCAPE,MAX_Y_LANDSCAPE,"Available Videos:      (EXIT)",&charsPrinted);
    i=0; row=1; vids=0;
    while(1){                          //list names
      lcd.SDFgetFileName(i++,name);    //get the name of the vid file number i
      if(name[0]==0x00) break;         //if name is invalid, meand end of files 
      if(strstr(name,".vid")!=0x00){   //if .vid extension is found in the file name: print      
        lcd.objButton(15,(row*30),MAX_X_LANDSCAPE-15,30+(row*30),DESELECTED,name);  row++;
        vids++;  
      }//else ignore name/file
    }
    
    while(lcd.touchScreen(&point)==INVALID); //wait for a touch to perform action
    row=point.y/30;                    //decode touch point by dividing it by 30 (240/8) which gives the 30 pixels spacing between buttons
    if(row==0){                        //touch on header (EXIT);
      lcd.SDFopenDir("..");            //return/go up to parent dir one level
      lcd.orientation(PORTRAIT_LOW);   //change to portrait mode     
      wait_ms(300); 
      return;                          //EXIT media()
    }else if(row > vids) continue;     //if touch on invalid row, where no button is present, go to top while(1)
    i=0;
    while(row){ //get name of obtained row
      lcd.SDFgetFileName(i++,name);    //get the name of the vid file number i  
      if(strstr(name,".vid")!=0x00) row--;   //if .vid extension is found in the file name: decrease row variable
    }
    //Try to play video
    cutFileExtension(name,".vid");    //cut to name the .vid extension  
    if(lcd.allocateVideoSD(name,&videoData)!=OK) continue; //try to allocate video, if fail, continue to top while(1)
    //up to here video is successfully allocated..
    currentFrame=0;  currentSecond=0; //reset variables
    lcd.playWAVFile(name,&charsPrinted); //open audio if any, must be named the same as the video expept for the .extension
    while(1){
      if(lcd.playVideoSD(0,0,videoData.framesPerSec)!=OK) break; //play video for 1 second(this equal the obtained frames per second parameter) break if error
      currentSecond++; currentFrame+=videoData.framesPerSec;
      if(lcd.touchScreen(&point)==VALID){  //check about each ~1 second for a touch, if Valid:
        lcd.pauseWAVFile();           //stop audio
        //draw buttons and progress bar
        drawButtonsAndProgress(currentFrame, videoData.totalFrames);
        wait_ms(300);
        while(1){
          while(lcd.touchScreen(&point)==INVALID || point.y<170); //while no valid touch or touch outside buttons
          if(point.y > 200) break;                              //if touch on buttons, break while(1) and go to next ifs
          //advance file to received touch in progress bar value...
          currentFrame=((unsigned long)point.x * (unsigned long)videoData.totalFrames) / MAX_X_LANDSCAPE; //obtain new current frame value 0-319
          currentFrame= (currentFrame/(unsigned long)videoData.framesPerSec)*((unsigned long)videoData.framesPerSec); //convert currentFrame to a factor of videoData.framesPerSecond
          currentSecond=(currentFrame/(unsigned long)videoData.framesPerSec);
          lcd.setFrameVideoSD(currentFrame);                    //set new obtained frame
          lcd.playVideoSD(0,0,1);                               //show new frame
          lcd.advanceWAVFile(currentSecond);                    //set new value to audio file
          //update buttons and progress bar
          drawButtonsAndProgress(currentFrame, videoData.totalFrames);
          wait_ms(50);
        }
        if(point.x < 160){           //touch on continue button
          lcd.objButton(0,200,159,230,SELECTED,"Continue");
          wait_ms(300);
          lcd.pauseWAVFile();        //resume audio
        }else{                       //touch on return button
          lcd.objButton(161,200,319,230,SELECTED,"Return...");
          lcd.stopWAVFile();
          wait_ms(300);
          break;                     //exit playback        
        }
      }
    }          
  }
}

/**************************************************/
void notes(){
  lcd.imageBMPSD(0,0,"Misc/notes");          //load notes design
  lcd.objButton(10,280,MAX_X_PORTRAIT-10,310,DESELECTED,"Return");
  drawHeader("Adjustments:");
  wait_ms(200);                              //A little delay to avoid fast image changing

  while(1){    
    while(lcd.touchScreen(&point)==INVALID); //wait for a touch to do something    
    if(point.y<65){                          //Touch on upper Icons
      //clear note block
      lcd.imageBMPSD(0,0,"Misc/notes");      //load notes design
      lcd.objButton(10,280,MAX_X_PORTRAIT-10,310,DESELECTED,"Return");
      drawHeader("Note pad:");
    }else if(point.y<280){                   //touch on notepad
      lcd.drawCircle(point.x,point.y,1,BLACK,FILL); //draw         
    }else{                                   //touch on return button
      lcd.objButton(10,280,MAX_X_PORTRAIT-10,310,SELECTED,"Return");    
      wait_ms(300);
      return;                                //exit
    }                                
  }                                 
}

/**************************************************/
void games(){
  int x;
  char hitFlag=0,hole,mole,moleCounter=20,points=0,pointsTotal[4]="00 ";        //array to store the points
  NUMBEROFBYTES charsPrinted;
  
  lcd.orientation(LANDSCAPE_LEFT); //set orientation as landscape  
  lcd.SDFopenDir("Games");          //Open the Games folder that contains the images of the Application

 while(1){                         //loop forever
  lcd.drawGradientRect(0,0,MAX_X_LANDSCAPE,MAX_Y_LANDSCAPE,BLACK,MAGENTA,VERTICAL); 
  lcd.setTextColour(WHITE);
  lcd.setTextSize(FONT5);
  lcd.setTextBackFill(TRANS);  
  lcd.string(10,80,MAX_X_LANDSCAPE,MAX_Y_LANDSCAPE,"MOLE STOMP!!!",&charsPrinted); //show name string
  wait_ms(1000);  
  lcd.string(22,130,MAX_X_LANDSCAPE,MAX_Y_LANDSCAPE,"GET READY!!!",&charsPrinted); //show ready string
  wait_ms(1500);
  lcd.imageBMPSD(0,0,"MoleArea");  //show area   
  lcd.setTextSize(FONT2);
  lcd.setTextBackFill(FILLED); 
  lcd.setTextBackColour(BLUE);     //set the all text background to blue  
  
  //Start the game!
  while(moleCounter>0){            //loop the game while moleCounter reaches zero moles
    mole=rand()%3;                 //get a random mole 0-2
    hole=rand()%7;                 //get a random hole 0-6
    showMole(mole,hole);           //show the random mole on the random hole
    for(x=0;x<3000;x++){            //wait some time for the player hit the mole(less time=more difficulty, more time=easy play)
      if(lcd.touchScreen(&point)==VALID){  //if we receive a touch on screen
        if(touchOnHole(hole)){     //if the touch is on the hole of the current mole
          hitFlag=1;               //turn on the hit mole flag
          break;                   //end the waiting time
        }
        if(point.x > 270 && point.y < 50) moleCounter=0; //touch on X symbol, end game
      }  
    }
    if(hitFlag==1){               //if the last mole was hit
      showMole(HITMOLE,hole);     //we show the hit mole
      points++;                   //increase hit mole counter or points
      hitFlag=0;                  //clear the hit flag
    }else{                        //if the last mole was missed
      showMole(MISSMOLE,hole);    //show the mole hiding
    }
    pointsTotal[0]=(points/10)+0x30;  //get the tens of the points and convert them to ascii
    pointsTotal[1]=(points%10)+0x30;  //get the ones of the points and convert them to ascii
    lcd.string(33,27,100,100,pointsTotal,&charsPrinted); //draw the points  
    wait_ms(350);
    showMole(MOLEHOLE,hole);          //show the bare hole
    moleCounter--;                    //decrease the mole counter
  }
  
  //Game over, display results
  lcd.setTextColour(YELLOW);
  lcd.setTextSize(FONT3);
  lcd.setTextBackFill(TRANS);    
  lcd.string(80,50,300,220,"Whacked Moles:",&charsPrinted);   
  lcd.setTextColour(BLUE);  
  lcd.string(153,75,300,220,pointsTotal,&charsPrinted); //draw the converted to ascii points array 
  lcd.setTextColour(RED);  
  lcd.setTextSize(FONT2);  
  lcd.string(50,140,319,239,"TOUCH TO RESTART",&charsPrinted);
  lcd.objButton(10,200,MAX_X_LANDSCAPE-10,230,DESELECTED,"Return");
  wait_ms(1000);

  while(lcd.touchScreen(&point)==INVALID);   //wait for a touch on screen to restart or exit
  if(point.y>200){                           //touch on return button
    lcd.objButton(10,200,MAX_X_LANDSCAPE-10,230,SELECTED,"Return");
    break;                                   //exit while(1) loop
  }//else re-start game
  moleCounter=20;                   //reset the moleCounter
  points=0;                         //reset points
  lcd.erase();                      //erase screen and restart all
 }   
  lcd.SDFopenDir("..");                                //return/go up to parent dir one level
  lcd.orientation(PORTRAIT_LOW);                       //change to portrait mode    
  wait_ms(300);
}

/**************************************************/
void music(){
  STATE state; static char pause=1;
  unsigned int dirs=0,songs=0;
  static unsigned int currentSong=0, volume=100;//static to save current song and volume even we exit function
  NUMBEROFBYTES charsPrinted;
  
  lcd.SDFopenDir("Music");          //Open the folder that contains the songs in .wav format
  lcd.SDFgetList(&dirs,&songs);     //get number of files/songs under the current folder "Music"
  
  lcd.setTextColour(WHITE);
  lcd.setTextSize(FONT3);
  lcd.setTextBackFill(TRANS);
  lcd.drawGradientRect(0,0,MAX_X_PORTRAIT,MAX_Y_PORTRAIT,BLACK,MAGENTA,VERTICAL);
  lcd.string(50,140,MAX_X_PORTRAIT,MAX_Y_PORTRAIT,"Music Player",&charsPrinted);
  wait_ms(1000);
  lcd.erase();  
  drawHeader("Music:");
  lcd.getWAVPlayState(&state);      //get playing state
  if(state==DISABLE) pause=1;       //if not playing, set pause to active
  drawControlPLAY(pause);           //draw button according to pause
  drawControlRR(DESELECTED);
  drawControlFF(DESELECTED); 
  //draw current volume bar
  lcd.drawRectangle(0,245,(volume*MAX_X_PORTRAIT)/(100),260,YELLOW,FILL);  //scale volume value to 0-239 pixels
  lcd.drawRectangle((volume*MAX_X_PORTRAIT)/(100),245,319,260,BLACK,FILL); //scale volume value to 0-239 pixels 
    
  while(1){
    lcd.getWAVPlayState(&state);                         //get playing state  
    if(state==DISABLE){pause=1; drawControlPLAY(pause);} //if not playing, set pause to active and update button
    if(pause==0) lcd.drawGradientRect(0,70,MAX_X_PORTRAIT,240,(rand()%0xFFFF),(rand()%0xFFFF),HORIZONTAL);
    
    wait_ms(100);
    if(lcd.touchScreen(&point)==VALID){           //ask for touch and if valid..
      if(point.y>265){                            //Touch on controls
        if(point.x<80){                           //touch on << icon
          drawControlRR(SELECTED);
          lcd.advanceWAVFile(0);                  //rewind song to beginning
          wait_ms(300);                           //wait                    
          drawControlRR(DESELECTED);
        }else if(point.x<160){                    //touch on Play/Pause icon
          if(state == ENABLE){                    //if playing
            lcd.pauseWAVFile();                   //pause playing
            pause=!pause;
          }else{                                  //begin to play any song
            lcd.SDFgetFileName(currentSong,name); //get the name of the song file number currentSong
            cutFileExtension(name,".wav");        //cut to name the .wav extension
            lcd.playWAVFile(name,&charsPrinted); //play file - returns the duration of the song in seconds
            lcd.drawRectangle(0,25,MAX_X_PORTRAIT,70,BLACK,FILL);   //erase previous name
            lcd.string(10,30,MAX_X_PORTRAIT,MAX_Y_PORTRAIT,name,&charsPrinted); //print new name
            pause=0; 
          }        
          wait_ms(300);          
        }else{ //point.x<240                      //touch on >> icon
          drawControlFF(SELECTED);
          lcd.stopWAVFile();                      //stop current playing song if any
          currentSong++;                          //advance current song
          if(currentSong>=songs) currentSong=0;   //check
          lcd.SDFgetFileName(currentSong,name);   //get the name of the song file number currentSong
          cutFileExtension(name,".wav");          //cut to name the .wav extension
          lcd.playWAVFile(name,&charsPrinted);    //play file
          lcd.drawRectangle(0,25,MAX_X_PORTRAIT,70,BLACK,FILL);   //erase previous name
          lcd.string(10,30,MAX_X_PORTRAIT,MAX_Y_PORTRAIT,name,&charsPrinted); //print new name         
          pause=0;
          wait_ms(300);                             //wait          
          drawControlFF(DESELECTED);
        }
        drawControlPLAY(pause);                   //update button        
      }else if(point.y>240){                      //Touch on volume bar
        volume=(point.x*100)/MAX_X_PORTRAIT;      //obtain new volume parameter by scaling to 0-239 pixels
        lcd.setVolumeWAV(volume);                 //set new volume to SmartGPU Audio
        //update volume bar
        lcd.drawRectangle(0,245,(volume*MAX_X_PORTRAIT)/(100),260,YELLOW,FILL);             //scale volume value to 0-239 pixels
        lcd.drawRectangle((volume*MAX_X_PORTRAIT)/(100),245,MAX_X_PORTRAIT,260,BLACK,FILL); //scale volume value to 0-239 pixels         
        wait_ms(50);
      }else if(point.y<20){                       //if touch on main header, go to main menu
        lcd.SDFopenDir("..");                     //return/go up to parent dir one level
        wait_ms(300);      
        return;
      }
    } 
  }
}

/**************************************************/
void wallpaper(){
  unsigned int dirs=0,walls=0, i=0;
  NUMBEROFBYTES charsPrinted;
  
  lcd.SDFopenDir("Wall") ;          //Open the folder that contains the wallpaper images
  lcd.SDFgetList(&dirs,&walls);     //get number of files/Pics under the current folder "Wall"
  
  lcd.setTextColour(WHITE);
  lcd.setTextSize(FONT3);
  lcd.setTextBackFill(TRANS);
  lcd.drawGradientRect(0,0,MAX_X_PORTRAIT,MAX_Y_PORTRAIT,BLACK,MAGENTA,VERTICAL);
  lcd.string(55,140,MAX_X_PORTRAIT,MAX_Y_PORTRAIT,"Wallpapers",&charsPrinted);
  wait_ms(1000);
 
  while(1){  
    lcd.SDFgetFileName(i,name);                        //get the name of the wall file number i
    cutFileExtension(name,".bmp");                     //cut to name the .bmp extension
    lcd.imageBMPSD(0,0,name);                          //Load image from SD card, all images are 240x320(full screen) so we load them from top left corner X:0,Y:0
    drawHeader("Wallpapers:");
    wait_ms(200);                                      //A little delay to avoid fast image changing    
    lcd.objButton(10,25,MAX_X_PORTRAIT-10,55,DESELECTED,"Set as Wall");    
    lcd.objButton(10,280,MAX_X_PORTRAIT-10,310,DESELECTED,"Return");
    
    while(lcd.touchScreen(&point)==INVALID);           //wait for a touch to do something    
    
    if(point.y > 280){                                 //if touch on "return" button, break to exit while(1);
      lcd.objButton(10,280,MAX_X_PORTRAIT-10,310,SELECTED,"Return");
      lcd.SDFopenDir("..");                            //return/go up to parent dir one level
      wait_ms(300);      
      return;                                          //EXIT                           
    }
    if(point.y < 60){                                  //if touch on "set as wall" button
      lcd.objButton(10,25,MAX_X_PORTRAIT-10,55,SELECTED,"Set as Wall");
      lcd.setTextSize(FONT2);
      lcd.string(22,140,MAX_X_PORTRAIT,MAX_Y_PORTRAIT,"Saved on EEPROM",&charsPrinted);
      saveWallpaperToEEPROM();                         //Save the current contents of "name" array to EEPROM
      wait_ms(500);
      continue;
    }     
    //check if we go to the next image, or to the previous one
    if(point.x>120){                                   //if the received touch was on the right side of the screen we advance the image, else we decrease and go to previous image
      i++;                                             //decrease image selector
      if(i>=walls){                                    //if we reach the position of the last image, we restart to image 0
        i=0;                 
      }        
    }else{                                             //touch on left side of screen
      if(i>0){                                         //if we can decrease i
        i--;    
      }else{                                           //if we decrease i will be less than zero, so we move to last image instead
        i=walls-1;  
      }
    }   
  }    
}

/***************************************************/
/***************************************************/
void initializeSmartGPU2(void){      //Initialize SMARTGPU2 Board
  lcd.reset();                       //physically reset SMARTGPU2
  lcd.start();                       //initialize the SMARTGPU2 processor
}

/***************************************************/
/***************************************************/
/***************************************************/
/***************************************************/
int main() {
  unsigned char icons;
    
  initializeSmartGPU2();           //Init communication with SmartGPU2 board
  
  lcd.baudChange(BAUD7);           //set high baud for advanced applications
  lcd.orientation(PORTRAIT_LOW);   //set orientation as portrait  
  lcd.initDACAudio(ENABLE);        //Turn on the Audio DACs
  lcd.audioBoost(ENABLE);          //ENABLE boost  
  lcd.SDFopenDir("FullGUI");       //Open the FullGUI folder that contains the images of the Application

  while(1){
    //draw MainMenu
    drawMainMenu();
    
    icons=getTouchIconMainMenu();  //ask for a touch on one of the icons of main menu and return icon#
    switch(icons){
      case 1: //case icon 1
        backlight();
      break;  
      case 2: //case icon 2
        //calculator();
      break;
      case 3: //case icon 3
        clocks();
      break;
      case 4: //case icon 4
        games();
      break;
      case 5: //case icon 5
        //maps();
      break;
      case 6: //case icon 6
        media();
      break;
      case 7: //case icon 7
        notes();
      break;
      case 8: //case icon 8
        photos();
      break;
      case 9: //case icon 9
        //wifi();
      break;
      case 10: //case icon 10
        //settings();
      break;      
      case 11: //case icon 11
        //calls();
      break; 
      case 12: //case icon 12
        music();
      break; 
      case 13: //case icon 13
        wallpaper();
      break;      
      default:
        //do nothing
      break;       
    }
  }  
}