Project tutorial
SmartGPU2 - Arduino Smartphone like GUI

SmartGPU2 - Arduino Smartphone like GUI

This project is about an arduino controlling the smartGPU2 intelligent graphics processor and creates an smart phone like interface.

  • 3,755 views
  • 2 comments
  • 12 respects

Components and supplies

About this project

This project was done in order to test the smartGPU2 graphics processor capabilities, via simple commands sent by the arduino, the GPU2 can create amazing graphics and even play audio!

The SmartGPU 2 is a powerful easy to use, intellectual property, graphics, audio, touchscreen and full datalogger processor embedded in a state-of-the-art ARM Cortex-M3 chip; its mounted on a board with a touchscreen color LCD. SmartGPU 2 doesn't need any configuration or programming on itself, it's a slave device that only receives orders. It's aimed to help developers to create advanced Graphical User Interfaces (GUIs) in a very easy way in just minutes, not days.

The Smart GPU 2 offers a simple yet effective serial interface UART to any host microcontroller that can communicate via a serial port(Arduino, Raspberry PI, mbed, PSOC4, PIC, Atmel, Freescale, STM, FPGA, PCs(RS232),8051 and low end 8 bit microcontrollers. All processor functions are received using simple commands via the serial interface. Smart GPU 2 processor can bring graphics, audio, touch, etc to any application or project without the need of having experience in handling LCDs and graphics algorithms.

Code

SmartGPU2 smartphone GUI demoC/C++
Use this together with the smartGPU2 arduino library available to download from the website http://www.vizictechnologies.com/#!smartgpu-2/c1rc2
/*********************************************************
VIZIC TECHNOLOGIES. COPYRIGHT 2014.
THE DATASHEETS, SOFTWARE AND LIBRARIES ARE PROVIDED "AS IS." 
VIZIC EXPRESSLY DISCLAIM ANY WARRANTY OF ANY KIND, WHETHER 
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
OR NONINFRINGEMENT. IN NO EVENT SHALL VIZIC BE LIABLE FOR 
ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, 
LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF 
PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, 
ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO 
ANY DEFENCE THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION,
OR OTHER SIMILAR COSTS.
*********************************************************/

/********************************************************
 IMPORTANT : This Example is created for the Arduino 1.0 Software IDE
********************************************************/

#include <SMARTGPU2.h>     //include the SMARTGPU2 library!

SMARTGPU2 lcd;             //create our object called LCD

//defines for GUI
#define HALFX       LCD_HEIGHT/2
#define HALFY       LCD_WIDTH/2
#define ICONSPACING (((MAX_X_PORTRAIT+1)-(((MAX_X_PORTRAIT+1)/50)*50))/(((MAX_X_PORTRAIT+1)/50)+1))

//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
const char iconNames[][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 X x Y EQUAL PARTS------------------------------------
  //Divide screen into X equal horizontal parts for icons
  icPress= (point.x/((MAX_X_PORTRAIT+1)/((MAX_X_PORTRAIT+1)/50)))+1; //LCD_HEIGHT    
  //Divide Screen into Y equal vertical parts for icons
  icPress = icPress+(((point.y-20)/((MAX_Y_PORTRAIT+1)/((MAX_Y_PORTRAIT+1)/50)))*((MAX_X_PORTRAIT+1)/50)); //LCD_WIDTH
  //------------------------------------------------------------------------------------------------- 
  return icPress; //return decoded coordinate from 1 to X icons
}

//obtain from EEPROM FLASH memory the name of the current stored wallpaper on the "name" array
void getCurrentWallFromEEPROM(void){
  lcd.fillBuffFromEEPROMPage(PAGE0); //copy PAGE0 to EEPROM RAM buffer
  lcd.readEEPROMBuff(name,0,14,0);   //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){
  lcd.initClearEEPROMBuff();                  //Initialize EEPROM RAM Buffer
  lcd.writeEEPROMBuff(name,0,sizeof(name),0); //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){
  unsigned int batteryPercentage = 65;                     //can be global variable to display the real battery consumption
  //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",0);             //draw Vizic string
  lcd.string((LCD_HEIGHT/2)-35,0,MAX_X_PORTRAIT,20,text,0); //draw string
  //draw battery icon according to the battery percentage variable
  lcd.drawRectangle(MAX_X_PORTRAIT-25,0,(MAX_X_PORTRAIT-25)+((batteryPercentage*15)/100),10,GREEN,FILL);
  lcd.drawRectangle(MAX_X_PORTRAIT-25,0,MAX_X_PORTRAIT-10,10,WHITE,UNFILL);
  lcd.drawRectangle(MAX_X_PORTRAIT-10,4,MAX_X_PORTRAIT-8,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      
}

 //function used by music
void drawControlRR(ACTIVE state){
  //draw button
  lcd.objButton(0,LCD_WIDTH-55,(LCD_HEIGHT/3)-1,LCD_WIDTH-5,state,"");
  //draw symbol
  lcd.drawTriangle(0+10,(LCD_WIDTH-55)+(((LCD_WIDTH-5)-(LCD_WIDTH-55))/2),0+((LCD_HEIGHT/6)-1),(LCD_WIDTH-55)+10,0+((LCD_HEIGHT/6)-1),(LCD_WIDTH-5)-10,BLACK,FILL);
  lcd.drawTriangle(0+((LCD_HEIGHT/6)-1),(LCD_WIDTH-55)+(((LCD_WIDTH-5)-(LCD_WIDTH-55))/2),0+((LCD_HEIGHT/3)-1)-10,(LCD_WIDTH-55)+10,0+((LCD_HEIGHT/3)-1)-10,(LCD_WIDTH-5)-10,BLACK,FILL);
}

//function used by music
void drawControlFF(ACTIVE state){
  //draw button  
  lcd.objButton(((LCD_HEIGHT/3)*2),LCD_WIDTH-55,MAX_X_PORTRAIT,LCD_WIDTH-5,state,"");    
  //draw symbol
  lcd.drawTriangle(LCD_HEIGHT-(((LCD_HEIGHT/3)-1)-10),(LCD_WIDTH-55)+10,LCD_HEIGHT-(((LCD_HEIGHT/3)-1)-10),(LCD_WIDTH-5)-10,LCD_HEIGHT-((LCD_HEIGHT/6)-1),(LCD_WIDTH-55)+(((LCD_WIDTH-5)-(LCD_WIDTH-55))/2),BLACK,FILL);  
  lcd.drawTriangle(LCD_HEIGHT-((LCD_HEIGHT/6)-1),(LCD_WIDTH-55)+10,LCD_HEIGHT-((LCD_HEIGHT/6)-1),(LCD_WIDTH-5)-10,LCD_HEIGHT-10,(LCD_WIDTH-55)+(((LCD_WIDTH-5)-(LCD_WIDTH-55))/2),BLACK,FILL);  
} 

//function used by music
void drawControlPLAY(char symbol){
  //draw button  
  lcd.objButton((LCD_HEIGHT/3),LCD_WIDTH-55,((LCD_HEIGHT/3)*2)-1,LCD_WIDTH-5,SELECTED,"");  
  //draw symbol
  if(symbol){      //PLAY
    lcd.drawTriangle((LCD_HEIGHT/3)+10,(LCD_WIDTH-55)+10,(LCD_HEIGHT/3)+10,(LCD_WIDTH-5)-10,((LCD_HEIGHT/3)*2)-10,(LCD_WIDTH-55)+(((LCD_WIDTH-5)-(LCD_WIDTH-55))/2),BLACK,FILL);
  }else{           //PAUSE
    lcd.drawRectangle((LCD_HEIGHT/3)+10,(LCD_WIDTH-55)+10,(LCD_HEIGHT/3)+(LCD_HEIGHT/8),(LCD_WIDTH-5)-10,BLACK,FILL);
    lcd.drawRectangle(((LCD_HEIGHT/3)*2)-(LCD_HEIGHT/8),(LCD_WIDTH-55)+10,((LCD_HEIGHT/3)*2)-10,(LCD_WIDTH-5)-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,LCD_HEIGHT-40,(LCD_WIDTH/2)-1,LCD_HEIGHT-10,DESELECTED,"Continue");
  lcd.objButton((LCD_WIDTH/2)+1,LCD_HEIGHT-40,MAX_X_LANDSCAPE,LCD_HEIGHT-10,DESELECTED,"Return...");
  lcd.drawRectangle(0,(LCD_WIDTH/2)+10,(currFrame*MAX_X_LANDSCAPE)/(totFrames),(LCD_WIDTH/2)+30,RED,FILL);                 //scale currentFrame value to 0-LCD_WIDTH pixels
  lcd.drawRectangle((currFrame*MAX_X_LANDSCAPE)/(totFrames),(LCD_WIDTH/2)+10,MAX_X_LANDSCAPE,(LCD_WIDTH/2)+30,BLACK,FILL); //scale currentFrame value to 0-LCD_WIDTH pixels 
}

//Main applications, the next applications are called by the main loop menu
/**************************************************/
/**************************************************/
/**************************************************/
//draws Main Menu
void drawMainMenu(void){  
  unsigned int i=0, j=0, k=0, xJump=ICONSPACING, yJump=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(not Wall set by user), just erase screen
  //now draw all top icons
  lcd.SDFopenDir("Ics");                     //open the folder with the icons
  for(i=0;i<((MAX_Y_PORTRAIT+1)/50);i++){
    for(j=0;j<((MAX_X_PORTRAIT+1)/50);j++){  
      lcd.imageBMPSD(xJump,yJump,(char*)iconNames[k++]);  //try to draw icon;  
      xJump+=50+ICONSPACING;
    }
    xJump=ICONSPACING;
    yJump+=50+ICONSPACING;
  }
  lcd.SDFopenDir("..");                      //return/go up to parent dir one level
  drawHeader("Main Menu");
  delay(350);                                //A little delay to avoid fast image changing   
}

/**************************************************/
void backlight(void){
  static unsigned char currentBacklightValue=100; //0-100
  
  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((MAX_X_PORTRAIT+1)/6,(MAX_Y_PORTRAIT+1)/4,MAX_X_PORTRAIT,MAX_Y_PORTRAIT,"Brightness Bar",0);
  lcd.objSlider(10,(MAX_Y_PORTRAIT+1)/4,MAX_X_PORTRAIT-10,((MAX_Y_PORTRAIT+1)/4)*2,currentBacklightValue,101,HORIZONTAL);
  lcd.objButton(10,MAX_Y_PORTRAIT-40,MAX_X_PORTRAIT-10,MAX_Y_PORTRAIT-10,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>((MAX_X_PORTRAIT+1)/4)) && (point.y<(((MAX_Y_PORTRAIT+1)/4)*2))){  //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,(MAX_Y_PORTRAIT+1)/4,MAX_X_PORTRAIT-10,((MAX_Y_PORTRAIT+1)/4)*2,currentBacklightValue,101,HORIZONTAL);     //update slider
      lcd.bright(currentBacklightValue);                                                                                          //set new brightness value
      delay(150);
    }
    if(point.y>(MAX_Y_PORTRAIT-40)){                                                                                              //if touch inside return button
      lcd.objButton(10,MAX_Y_PORTRAIT-40,MAX_X_PORTRAIT-10,MAX_Y_PORTRAIT-10,SELECTED,"Return");
      delay(300);
      return;                                                                                                                     //exit function
    }     
  }
}

/**************************************************/
void clock(void){
  unsigned int hours=4,mins=48,secs=0,i=0;
  unsigned int xs,ys,xm,ym,xh,yh;
  int angleH,angleM,angleS;
  unsigned int handHour=((MAX_X_PORTRAIT+1)/5);//hand size
  unsigned int handMin =handHour+10; //hand size
  unsigned int handSec =handMin+20; //hand size 
  
  lcd.drawGradientRect(0,0,MAX_X_PORTRAIT,MAX_Y_PORTRAIT,BLACK,MAGENTA,VERTICAL); //draw a fullscreen gradient rectangle
  lcd.objButton(10,MAX_Y_PORTRAIT-40,MAX_X_PORTRAIT-10,MAX_Y_PORTRAIT-10,DESELECTED,"Return");
  drawHeader("Clocks:");    
  //drawClock Body
  lcd.drawCircle(HALFX,HALFY,(MAX_X_PORTRAIT+1)/3,BLACK,FILL);
  lcd.drawCircle(HALFX,HALFY,(MAX_X_PORTRAIT+1)/3,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>(MAX_Y_PORTRAIT-40)){               //if touch inside return button
          lcd.objButton(10,MAX_Y_PORTRAIT-40,MAX_X_PORTRAIT-10,MAX_Y_PORTRAIT-10,SELECTED,"Return");
          delay(300);
          return; //exit function
        }    
      }
      delay(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 pics=0;
  static unsigned int i=0;                             //static to save last image position even we exit function
  
  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((MAX_X_LANDSCAPE+1)/3,(MAX_Y_LANDSCAPE+1)/3,MAX_X_LANDSCAPE,MAX_Y_LANDSCAPE,"Photo Gallery",0);
  lcd.setTextSize(FONT2);  
  delay(1000);
  lcd.SDFopenDir("Photos");                            //open the folder with the photos
  lcd.SDFgetList(0,&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 must be full screen so we load them from top left corner X:0,Y:0
    delay(200);                                        //A little delay to avoid fast image changing    
    lcd.string((MAX_X_LANDSCAPE+1)/4,MAX_Y_LANDSCAPE-20,MAX_X_LANDSCAPE,MAX_Y_LANDSCAPE,"<Tap center to Exit>",0); //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>(MAX_X_LANDSCAPE-100)){                 //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    
  delay(300);
}

/**************************************************/
void media(){
  unsigned int i=0, row=0, vids=0;
  unsigned long currentFrame=0, currentSecond=0;
  VIDDATA videoData;
  
  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((MAX_X_LANDSCAPE+1)/3,(MAX_Y_LANDSCAPE+1)/3,MAX_X_LANDSCAPE,MAX_Y_LANDSCAPE,"Video Player",0);  
  lcd.stopWAVFile();                   //stop current playing song if any   
  delay(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)",0);
    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     
      delay(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,0);          //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);
        delay(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);
          delay(50);
        }
        if(point.x < 160){           //touch on continue button
          lcd.objButton(0,200,159,230,SELECTED,"Continue");
          delay(300);
          lcd.pauseWAVFile();        //resume audio
        }else{                       //touch on return button
          lcd.objButton(161,200,319,230,SELECTED,"Return...");
          lcd.stopWAVFile();
          delay(300);
          break;                     //exit playback        
        }
      }
    }          
  }
}

/**************************************************/
void notes(){
  lcd.imageBMPSD(0,0,"Misc/notes");          //load notes design
  lcd.objButton(10,MAX_Y_PORTRAIT-40,MAX_X_PORTRAIT-10,MAX_Y_PORTRAIT-10,DESELECTED,"Return");
  drawHeader("Adjustments:");
  delay(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,MAX_Y_PORTRAIT-40,MAX_X_PORTRAIT-10,MAX_Y_PORTRAIT-10,DESELECTED,"Return");
      drawHeader("Note pad:");
    }else if(point.y<(MAX_Y_PORTRAIT-40)){   //touch on notepad
      lcd.drawCircle(point.x,point.y,1,BLACK,FILL); //draw
    }else{                                   //touch on return button
      lcd.objButton(10,MAX_Y_PORTRAIT-40,MAX_X_PORTRAIT-10,MAX_Y_PORTRAIT-10,SELECTED,"Return");    
      delay(300);
      return;                                //exit
    }                                
  }                                 
}

/**************************************************/
void games(){

}

/**************************************************/
void settings(){
  
}

/**************************************************/
void music(){
  STATE state; static char pause=1;
  unsigned int songs=0;
  static unsigned int currentSong=0, volume=100;//static to save current song and volume even we exit function

  lcd.SDFopenDir("Music");          //Open the folder that contains the songs in .wav format
  lcd.SDFgetList(0,&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((MAX_X_PORTRAIT+1)/4,(MAX_Y_PORTRAIT+1)/2,MAX_X_PORTRAIT,MAX_Y_PORTRAIT,"Music Player",0);
  delay(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,MAX_X_PORTRAIT,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,random(0,65536),random(0,65536),HORIZONTAL);
    
    delay(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
          delay(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,0);              //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,0); //print new name
            pause=0; 
          }        
          delay(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,0);                //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,0); //print new name         
          pause=0;
          delay(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         
        delay(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
        delay(300);      
        return;
      }
    } 
  }
}

/**************************************************/
void wallpaper(){
  unsigned int walls=0, currentWall=0, i=0;
  
  lcd.SDFopenDir("Wall") ;          //Open the folder that contains the wallpaper images
  lcd.SDFgetList(0,&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((MAX_X_PORTRAIT+1)/4,(MAX_Y_PORTRAIT+1)/2,MAX_X_PORTRAIT,MAX_Y_PORTRAIT,"Wallpapers",0);
  delay(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:");
    delay(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
      delay(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",0);
      saveWallpaperToEEPROM();                         //Save the current contents of "name" array to EEPROM
      delay(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;  
      }
    }   
  }    
}

/**************************************************/
/**************************************************/
//Initial setup
void setup() { //initial setup
  //Those two functions must always be called for SMARTGPU2 support
  lcd.init();  //configure the serial and pinout of arduino board for SMARTGPU2 support
  lcd.start(); //initialize the SMARTGPU2 processor
}

/**************************************************/
/****************** MAIN LOOP *********************/
/**************************************************/
/**************************************************/
void loop() { //main loop
  unsigned char icons;
  
  lcd.baudChange(BAUD5);           //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
        clock();
      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;       
    }
  }  
}

Schematics

SmartGPU2 Arduino Connections
Just mount the smartGPU2 as an arduino shield to your arduino!
Smartgpu2%20arduino

Comments

Similar projects you might like

DIY Voltmeter Using Arduino and Smartphone

Project tutorial by IoT_hobbyist

  • 2,980 views
  • 3 comments
  • 30 respects

SmartGPU2 - Arduino Oscilloscope

Project showcase by Vizic Technologies

  • 15,514 views
  • 7 comments
  • 32 respects

Image transmit and Control by Smartphone 4WD Robot Car

Project showcase by Alf81010

  • 1,834 views
  • 0 comments
  • 12 respects

IoT Notes Printer: Your Smartphone Notes on Paper

Project tutorial by Daniele Mazzei and Luigi Francesco Cerfeda

  • 11,925 views
  • 2 comments
  • 32 respects

SmartPhone Controlled RGB MOOD Light

Project tutorial by Prajjwal Nag

  • 5,724 views
  • 1 comment
  • 10 respects

Control Arduino Using Smartphone via USB with Blynk App

Project tutorial by Smart Technology

  • 3,179 views
  • 1 comment
  • 3 respects
Add projectSign up / Login