My ELEC2645 joystick project Tetris Game NAME: JIANWEI CHEN SID: 200879849

Dependencies:   N5110 SDFileSystem mbed

Files at this revision

API Documentation at this revision

Comitter:
cjw851102
Date:
Thu May 05 09:18:01 2016 +0000
Parent:
3:5494a0fb3a33
Commit message:
Final version

Changed in this revision

Game.h Show annotated file Show diff for this revision Revisions of this file
Joystick.h Show annotated file Show diff for this revision Revisions of this file
Patterns.h Show annotated file Show diff for this revision Revisions of this file
SDFileSystem.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
main.h Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
diff -r 5494a0fb3a33 -r 463abe5f5135 Game.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Game.h	Thu May 05 09:18:01 2016 +0000
@@ -0,0 +1,816 @@
+/**
+@file Game.h
+@brief Header file containing functions prototypes, defines and global variables for the tetris game.
+@brief Revision 1.0.
+@author JIANWEI CHEN
+@date   May 2016
+*/
+
+#ifndef GAME_H
+#define GAME_H
+
+#include "mbed.h"
+#include "Patterns.h"
+#include "N5110.h"
+#include "SDFileSystem.h"
+#include "main.h"
+
+//! Create patterns object
+Patterns patterns;
+/**
+Create ticker object for game
+@brief ticker to control the speed of game
+*/
+Ticker game;
+
+////////////////////////////////////////////////////////
+// Variables
+////////////////////////////////////////////////////////
+
+int xOld; /*!< Variable for storing the pattern previous position when game is runnung */
+int typeCount = 0; /*!< Variable for counting elements in array typeArray[100]*/
+int nextTypeCount; /*!< Variable to show the position of next element in typeArray[100] i.e. nextTypeCount=typeCount+1*/
+
+/** Flag to show left hand side conllision of pattern
+@note flag = 0 - there is no collision on the left
+@note flag = 1 - there is collision on the left
+*/
+int left_collision_flag = 0;
+
+/** Flag to show right hand side conllision of pattern
+@note flag = 0 - there is no collision
+@note flag = 1 - there is collision
+*/
+int right_collision_flag = 0;
+
+/** Flag to show bottom conllision of pattern
+@note flag = 0 - there is no collision
+@note flag = 1 - there is collision
+*/
+int bottom_collision_flag = 0;
+
+/** Flag to show top conllision of pattern
+@note flag = 0 - there is no collision
+@note flag = 1 - there is collision
+*/
+int top_collision_flag = 0;
+
+/** Flag to show if there is pixels set on the 4 pixels distance away from the bottom of pattern
+@brief if flag = 0, user can pull joystick down to make pattern falling faster
+@note flag = 0 - there is no collision
+@note flag = 1 - there is collision
+*/
+int fastmove_bottom_collision_flag = 0;
+
+/** Flag to show if allow patterns to rotate
+@note flag = 0 - allow
+@note flag = 1 - not allow
+*/
+int rotation_collision_flag = 0;
+
+/** Two dimension array to store current pattern pixels setting in a 6x6 square
+@note For example, if current pattern is "L"
+@note the pixels setting is
+@note 1 1 0 0 0 0
+@note 1 1 0 0 0 0
+@note 1 1 0 0 0 0
+@note 1 1 0 0 0 0
+@note 1 1 1 1 0 0
+@note 1 1 1 1 0 0
+*/
+int pattern_buffer[6][6];
+
+/** Array to store types of pattern
+@brief 100 random integers in the range of 0~6
+@brief will be stored in the array in order to generate
+@brief random type of pattern each time new pattern is generated
+*/
+int typeArray[100];
+int buffer[84][48]; /*!< Array to store whole screen pixel settings */
+int score=0; /*!< Variable to store score in the game */
+volatile int g_game_flag = 0; /*!< Flag for game ticker */
+
+/** Struct for position
+@brief Contains the pattern position(x,y),
+@brief pattern type and rotation
+*/
+struct Position {
+    float x;
+    float y;
+    int type;
+    int rotation;
+};
+typedef struct Position position;
+position pos;
+
+////////////////////////////////////////////////////////////////////////
+// Functions
+////////////////////////////////////////////////////////////////////////
+/**
+Game ticker isr function
+*/
+void game_isr();
+
+/**
+Initialise the variables in game
+*/
+void init_game();
+
+/** Drawing the pattern at position (x,y)
+@param type - type of pattern (0~6)
+@param rotation - rotation of pattern (0~3)
+@param x - x co-ordinate of pattern, which is the top left corner pixel of 6x6 square
+@param y - y co-ordinate of pattern, which is the top left corner pixel of 6x6 square
+@param fill - fill = 0 white, fill = 1 black
+*/
+void drawPattern(int type,int rotation,int x,int y,int fill);
+
+/**Left collision detect
+@brief Function to check the left collision of current falling pattern and set the left_collision_flag
+*/
+void left_collisionDetect();
+
+/**Right collision detect
+@brief Function to check the right collision of current falling pattern and set the left_collision_flag
+*/
+void right_collisionDetect();
+
+/**Bottom collision detect
+@brief Function to check the bottom collision of current falling pattern and set the right_collision_flag
+*/
+void bottom_collisionDetect();
+
+/**top collision detect
+@brief Function to check the top collision of current falling pattern and set the top_collision_flag
+*/
+void top_collisionDetect();
+
+/**Rotation collision detect
+@brief Function to check if the program should allow user to rotate the pattern and set the rotation_collision_flag
+*/
+void rotation_collisionDetect();
+
+/**Fast move collision detect
+@brief Function to check if the program should allow user to move the pattern falling faster and set the fastmove_collision_flag
+@note check the 4 pixels distance away from the bottom of pattern
+*/
+void fastmove_bottom_collisionDetect();
+
+/**Get pattern pixel settings
+@brief Function to get the current falling pattern pixel settings
+@note pixels setting will be store in pattern_buffer[6][6];
+@param type - type of pattern (0~6)
+@param rotation - rotation of pattern (0~3)
+*/
+void get_pattern(int type, int rotatin);
+
+/**Scan the whole screen pixel settings
+@brief Function to store the whole screen pixel settings and store in buffer[84][48]
+*/
+void scan();
+
+/** Cancel the filled lines and add the score
+@brief Function to check if there are lines filled
+@brief if one line is filled, cancel it and move the pixels above this line down and add the score
+*/
+void cancelLine();
+
+/**
+Game finish animations
+*/
+void finishAnimation();
+
+/** User press button when game is in process
+@brief When button pressed in the game, ask user if they want to exit the game
+@return TRUE - exit the game  FALSE - contiute the game
+*/
+bool buttonPressedInGame();
+
+/**Save the highest score to SD card
+@param score - a integer number need to save to SD card
+*/
+void save_score_SD(int score);
+
+/**
+Read the highest score from SD card
+*/
+int read_score_SD();
+
+/**
+Complete tetris game
+*/
+void tetis_game();
+
+
+/////////////////////////////////////////////////
+/// Function Definitions
+/////////////////////////////////////////////////
+
+void tetis_game()
+{
+    bool exitGame; //bool variable to save the exit game decision when button pressed
+    while (1) {
+        if(g_game_flag==1) {
+            g_game_flag = 0;
+
+            exitGame=buttonPressedInGame(); //check if user press button and get the decision
+            if(exitGame) { // exit game
+                break; //jump out of while loop
+            }
+
+            pos.type = typeArray[typeCount]; //get the pattern type
+            nextTypeCount=typeCount+1;
+            if (nextTypeCount>99) { //start from the first element in type array
+                nextTypeCount=0;
+            }
+            drawPattern(typeArray[nextTypeCount],0,55,41,1);// draw next pattern on the right hand side of screen
+            if (pos.y >= -5) { // when pattern start falling, clear previous pattern
+                drawPattern(pos.type,pos.rotation,xOld,pos.y-1,0);
+            }
+
+            updateJoystick(); //get the joystick direction
+
+            top_collisionDetect(); // check if current pattern touch the top
+            if (top_collision_flag == 1) { // if touch the top, finish the game
+                red_led=1;
+                green_led=0;
+                //play sound at end of game
+                for(double i=1; i>=0; i-=0.1) {
+                    buzzer = i;
+                    wait(0.2);
+                }
+                buzzer = 0;
+                finishAnimation(); //finish animation
+                lcd.clear();
+                int stored_score=read_score_SD();
+                if (score>stored_score) { // if score is larger than highest score, save it to SD card
+                    save_score_SD(score);
+                }
+                // show the score
+                char scoreBuffer[14];
+                sprintf(scoreBuffer,"%d",score);
+                lcd.printString("SCORE IS: ",10,2);
+                lcd.printString(scoreBuffer,35,4);
+                lcd.refresh();
+                wait(3.0);
+                lcd.clear();
+                state=0; // back to the main menu
+                break;
+            }
+
+            //move patterns according to joystick direction
+            switch(joystick.direction) {
+                case UP: // rotation
+                    rotation_collision_flag = 0;
+                    rotation_collisionDetect(); // check if allow rotation
+                    if(rotation_collision_flag == 0) { // allow rotation
+                        pos.rotation++;
+                        if (pos.rotation>3) {
+                            pos.rotation=0;
+                        }
+                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
+                    } else {// not allow rotation
+                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
+                    }
+                    break;
+                case DOWN: // faster moving down
+                    fastmove_bottom_collision_flag = 0;
+                    fastmove_bottom_collisionDetect();
+                    if (fastmove_bottom_collision_flag == 0) {// allow faster move
+                        pos.y +=4; // move pattern down by 4 pixels distance
+                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
+                    } else {
+                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
+                    }
+                    break;
+                case RIGHT: // move right
+                    right_collision_flag = 0;
+                    right_collisionDetect(); // detect right collision
+                    if( right_collision_flag == 0) { // allow move right
+                        pos.x +=2;
+                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
+                    } else { // not allow move right
+                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
+                        right_collision_flag = 0;
+                    }
+                    break;
+                case LEFT: //move left
+                    left_collision_flag = 0;
+                    left_collisionDetect(); // detect left collision
+                    if( left_collision_flag == 0) {// allow move left
+                        pos.x -=2;
+                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
+                    } else { // not allow move left
+                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
+                        left_collision_flag = 0;
+                    }
+
+                    break;
+                case CENTRE: // joystick in centre
+                    drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
+                    break;
+                case  UNKNOWN:
+                    drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
+                    break;
+            }
+
+            xOld = pos.x; //store previous pattern x co-codinate
+
+            bottom_collisionDetect(); // bottom collision detect
+            if (bottom_collision_flag == 0) { // no collision
+                pos.y++; // keep moving pattern down
+                buzzer = 0; // turn off buzzer
+            } else { // bottom collision
+                drawPattern(pos.type,pos.rotation,pos.x,pos.y,1); // fix pattern
+                cancelLine(); // check filled lines and add score
+                pos.x = 10; // new pattern will fall from the centre
+                pos.y = -6;
+                pos.rotation=0;
+                drawPattern(typeArray[nextTypeCount],pos.rotation,55,41,0);// clear the old next pattern show on RHS of screen
+                typeCount ++; //new type of pattern
+                if (typeCount >99) {
+                    typeCount = 0;
+                }
+            }
+            lcd.refresh();
+        }
+        sleep(); // go to sleep mode unless ticker interupt
+    }
+}
+
+
+void init_game()
+{
+    pos.x = 10;
+    pos.y = -6;
+    pos.rotation=0;
+    typeCount=0;
+    green_led=1; // turn on green led
+    //generate 100 random integers in the range of 0~6
+    //and store in typeArray
+    for(int i=0; i<=99; i++) {
+        typeArray[i] = rand()%7;
+    }
+
+    //gaming screen
+    lcd.drawLine(30,0,30,47,1);
+    lcd.printString("Level:",42,0);
+    lcd.printString("Score:",42,2);
+    lcd.printString("0",42,3);
+    lcd.printString("Next:",42,4);
+
+    //play sound at begining of game
+    for(double i=0; i<=1.0; i+=0.1) {
+        buzzer = i;
+        wait(0.2);
+    }
+    buzzer = 0;
+}
+
+
+void get_pattern(int type, int rotation)
+{
+    for(int i=0; i<=5; i++) {
+        for(int j=0; j<=5; j++) {// patterns.getPatterns(type,rotation,j,i) return pattern[type][rotation][y][x];
+            pattern_buffer[i][j] = patterns.getPatterns(type,rotation,j,i);
+        }
+    }
+}
+
+
+void scan()
+{
+    //screen has 84x48 pixels
+    for (int i=0; i<=83; i++) {
+        for (int j=0; j<=47; j++) {
+            if(lcd.getPixel(i,j)) { //if pixel is set
+                buffer[i][j] = 1;
+            } else { // pixel is clear
+                buffer[i][j] = 0;
+            }
+        }
+    }
+}
+
+// draw pattern at (x,y)
+void drawPattern(int type,int rotation,int x,int y,int fill)
+{
+    get_pattern(type,rotation); // get the pattern pixel settings, which store in pattern_buffer
+    for(int i=x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square
+        for(int j=y; j <= y+5; j++) {
+            if (j>=0) {
+                if(pattern_buffer[i-x][j-y]==1) {//pixel setting is 1
+                    if (fill==0) { //draw white pattern
+                        if (j<=47 && i>=0) { // draw pattern inside the screen
+                            lcd.clearPixel(i,j);
+                        }
+                    } else if (fill==1) { //draw black pattern
+                        if (j<=47 && i>=0) {
+                            lcd.setPixel(i,j);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+void left_collisionDetect()
+{
+    int left_boundary[6][6];
+    get_pattern(pos.type,pos.rotation);
+
+    /* get the left boundary pixel settings
+       e.g: if pattern is L
+       left boundary is
+       1 0 0 0 0 0
+       1 0 0 0 0 0
+       1 0 0 0 0 0
+       1 0 0 0 0 0
+       1 0 0 0 0 0
+       1 0 0 0 0 0
+    */
+    for (int j=0; j<=5; j++) { //
+        for (int i=0; i<=5; i++) {
+            if (pattern_buffer[i][j]==1) {
+                left_boundary[i][j]=1;
+                for(int k=i+1; k<=5; k++) {
+                    left_boundary[k][j] = 0;
+                }
+                break;
+            } else {
+                left_boundary[i][j]=0;
+            }
+        }
+    }
+
+    //check left collision
+    int x = pos.x;
+    int y = pos.y;
+    if (x<0) { //for all the pattern, when x<0, pattern is on the most LHS of screen
+        left_collision_flag = 1;
+    } else { //check the pixel status away from left boundary for one pixel distance
+        for(int i=x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square
+            for(int j=y; j <= y+5; j++) {
+                if(left_boundary[i-x][j-y]==1) {
+                    if(i == 0) { // pattern at most LHS of screen
+                        left_collision_flag = 1;
+                        break; // don't need to check the other pixels at same x, jump out of inner for loop
+                    } else if (lcd.getPixel(i-1,j)) { //check one pixel away from left boundary
+                        left_collision_flag = 1;
+                        break;
+                    } else {
+                        left_collision_flag = 0;
+                    }
+                }
+            }
+            if (left_collision_flag == 1) {
+                break;// jump out of inner for loop
+            }
+        }
+    }
+}
+
+
+void right_collisionDetect()
+{
+    int right_boundary[6][6];
+    get_pattern(pos.type,pos.rotation);
+
+    /* get the right boundary pixel settings
+       e.g: if pattern is L
+       left boundary is
+       0 0 1 0 0 0
+       0 0 1 0 0 0
+       0 0 1 0 0 0
+       0 0 1 0 0 0
+       0 0 0 1 0 0
+       0 0 0 1 0 0
+    */
+    for (int j=0; j<=5; j++) {
+        for (int i=5; i>=0; i--) {
+            if (pattern_buffer[i][j]==1) {
+                right_boundary[i][j]=1;
+                for(int k=i-1; k>=0; k--) {
+                    right_boundary[k][j] = 0;
+                }
+                break;
+            } else {
+                right_boundary[i][j]=0;
+            }
+        }
+    }
+
+    //check right collision
+    int x = pos.x;
+    int y = pos.y;
+    for(int i = x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square
+        for(int j=y; j <= y+5; j++) {
+            if(right_boundary[i-x][j-y]==1) {
+                if(j>=0) {
+                    if(i >= 29) { // most RHS of gaming screen
+                        right_collision_flag = 1;
+                        break;
+                    } else if (lcd.getPixel(i+1,j)) {//check the pixel status away from right boundary for one pixel distance
+                        right_collision_flag = 1;
+                        break;
+                    } else {
+                        right_collision_flag = 0;
+                    }
+                }
+            }
+        }
+        if (right_collision_flag == 1) {
+            break;
+        }
+    }
+}
+
+
+void bottom_collisionDetect()
+{
+    int bot_boundary[6][6];
+    get_pattern(pos.type,pos.rotation);
+
+    /* get the left boundary pixel settings
+       e.g: if pattern is L
+       left boundary is
+       0 0 0 0 0 0
+       0 0 0 0 0 0
+       0 0 0 0 0 0
+       0 0 0 0 0 0
+       0 0 0 0 0 0
+       1 1 1 1 0 0
+    */
+    for (int i=0; i<=5; i++) {
+        for (int j=5; j>=0; j--) {
+            if (pattern_buffer[i][j]==1) {
+                bot_boundary[i][j]=1;
+                for(int k=j-1; k>=0; k--) {
+                    bot_boundary[i][k] = 0;
+                }
+                break;
+            } else {
+                bot_boundary[i][j]=0;
+            }
+        }
+    }
+
+    //check bottom collision
+    int x = pos.x;
+    int y = pos.y;
+    for(int i = x; i <= x+5; i++) { //check from left
+        for(int j=y+5; j >= y; j--) { //check from bottom
+            if (j>=-1) { //start check when pattern fall in the screen
+                if(bot_boundary[i-x][j-y]==1) {
+                    if(j >= 47) { // pattern at bottom
+                        bottom_collision_flag = 1;
+                        break; // jump out of inner for loop
+                    } else if (lcd.getPixel(i,j+1)) {//check the pixel status away from bottom boundary for one pixel distance
+                        bottom_collision_flag = 1;
+                        break;
+                    } else {
+                        bottom_collision_flag = 0;
+                    }
+                }
+            } else { //at bottom of screen
+                bottom_collision_flag = 0;
+            }
+        }
+        if( bottom_collision_flag == 1) {
+            break; // jump out of inner for loop
+        }
+    }
+}
+
+
+void rotation_collisionDetect()
+{
+    int rotation = pos.rotation+1;
+    if (rotation>3) {
+        rotation=0;
+    }
+    get_pattern(pos.type,rotation);
+
+    //check pixel status of upcoming rotation
+    int x = pos.x;
+    int y = pos.y;
+    for(int i = x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square
+        for(int j=y; j <= y+5; j++) {
+            if(pattern_buffer[i-x][j-y]==1) {
+                if(i<0) { // out of LHS screen
+                    rotation_collision_flag = 1;
+                } else if(lcd.getPixel(i,j)) { // there is pixel set
+                    rotation_collision_flag = 1;
+                    break; //jump out of inner for loop
+                } else {
+                    rotation_collision_flag = 0;
+                }
+            }
+        }
+        if (rotation_collision_flag == 1) {
+            break; //jump out of inner for loop
+        }
+    }
+}
+
+
+void top_collisionDetect()
+{
+    if (pos.y==-6) { //pattern is about to fall
+        bottom_collisionDetect();
+        if (bottom_collision_flag == 1) { //if can't fall
+            top_collision_flag = 1; // top collision
+        } else {
+            top_collision_flag = 0;
+        }
+    }
+}
+
+
+void fastmove_bottom_collisionDetect()
+{
+    int bot_boundary[6][6];
+    get_pattern(pos.type,pos.rotation);
+
+    // get the bottom boundary pattern
+    for (int i=0; i<=5; i++) {
+        for (int j=5; j>=0; j--) {
+            if (pattern_buffer[i][j]==1) {
+                bot_boundary[i][j]=1;
+                for(int k=j-1; k>=0; k--) {
+                    bot_boundary[i][k] = 0;
+                }
+                break;
+            } else {
+                bot_boundary[i][j]=0;
+            }
+        }
+    }
+
+    //check bottom collision for 4 pixel distance away from bottom boundary
+    int x = pos.x;
+    int y = pos.y;
+    for(int i = x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square
+        for(int j=y+5; j >= y; j--) {
+            if (j>=-1) {
+                if(bot_boundary[i-x][j-y]==1) {
+                    if(j >= 42) { // pattern is about to fall on the bottom
+                        fastmove_bottom_collision_flag = 1;
+                        break;
+                    } else if (lcd.getPixel(i,j+4)) {//check bottom collision for 4 pixel distance away from bottom boundary
+                        fastmove_bottom_collision_flag = 1;
+                        break;
+                    } else {
+                        fastmove_bottom_collision_flag = 0;
+                    }
+                }
+            } else {
+                fastmove_bottom_collision_flag = 0;
+            }
+        }
+        if( fastmove_bottom_collision_flag == 1) {
+            break;
+        }
+    }
+}
+
+
+void game_isr()
+{
+    g_game_flag = 1;
+}
+
+
+void cancelLine()
+{
+    // int linePattern[30][2]; //the pixel setting for one line(30x2 square)
+    int count; // count setting pixels two by two
+    for(int j=0; j<=46; j+=2) {
+        for(int i=0; i<=29; i++) {
+            if (lcd.getPixel(i,j)==0||lcd.getPixel(i,j+1)==0) { // there is clear pixel
+                count=0;
+                break;
+            } else if (lcd.getPixel(i,j)&&lcd.getPixel(i,j+1)) {
+                count++;
+            }
+        }
+        if(count==30) { // one line is filled
+            count=0; // reset the variable count
+            lcd.drawRect(0,j,29,1,2); //clear the line
+            buzzer = 0.5;
+            score+=10;  // add the score
+            //update the score
+            char scoreBuffer[14];
+            sprintf(scoreBuffer,"%d",score);
+            lcd.printString(scoreBuffer,42,3);
+            scan();
+            // move the patterns above the line down for 2 pixels' hight
+            for (int x=0; x<=29; x++) {
+                for (int y=j; y>=0; y--) {
+                    if (buffer[x][y]) {
+                        lcd.clearPixel(x,y);
+                        lcd.setPixel(x,y+2);
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+void finishAnimation()
+{
+    for (int j=47; j>=0; j--) {
+        lcd.drawRect(0,j,29,1,1);
+        wait(0.05);
+        lcd.refresh();
+    }
+}
+
+
+bool buttonPressedInGame()
+{
+    bool exit_game;
+    if (g_button_flag) { // user press button finish game
+        g_button_flag=0;
+        scan(); // save the currnet gaming screen
+        game.detach(); // detach the game ticker
+        lcd.clear();
+        while(1) {
+            lcd.printString("Exit The Game?",1,1);
+            lcd.printString("YES",38,3);
+            lcd.printString("NO",38,4);
+            pointer(); // invoke pointer function
+            if (g_button_flag) {
+                g_button_flag=0;
+                if(pointer_position==0) { //"YES" -exit game
+                    lcd.clear();
+                    state=0; // back to main menu
+                    pointer_position=0;
+                    exit_game=true;
+                    int stored_score=read_score_SD();
+                    if (score>stored_score) { // if the score is higher than highest score, save it
+                        save_score_SD(score);
+                    }
+                    score=0; //clear socre
+                    red_led=1;
+                    green_led=0;
+                    break;
+                } else { //"NO" - continue the game
+                    exit_game=false;
+                    if(state==3) { // game level is easy
+                        lcd.clear();
+                        for(int i=0; i<=83; i++) { // back to the gaming screen before press button
+                            for(int j=0; j<=47; j++) {
+                                if(buffer[i][j]) {
+                                    lcd.setPixel(i,j);
+                                }
+                            }
+                        }
+                        game.attach(&game_isr,0.2); // easy game
+                        exit_game=false;
+                        break;
+                    } else if(state==4) {// game level is hard
+                        lcd.clear();
+                        for(int i=0; i<=83; i++) {// back to the gaming screen before press button
+                            for(int j=0; j<=47; j++) {
+                                if(buffer[i][j]) {
+                                    lcd.setPixel(i,j);
+                                }
+                            }
+                        }
+                        game.attach(&game_isr,0.1);// hard game
+                        break;
+                    }
+                }
+                break;
+            }
+        }
+    }
+    if(exit_game) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+
+int read_score_SD()
+{
+    fp = fopen("/sd/topscore.txt", "r"); //open file
+    int stored_top_score;
+    fscanf(fp, "%d",&stored_top_score); // ensure data type matches - note address operator (&)
+    fclose(fp);  // ensure you close the file after reading
+    return stored_top_score;
+}
+
+
+void save_score_SD(int score)
+{
+    fp = fopen("/sd/topscore.txt", "w");
+    fprintf(fp, "%d",score); // ensure data type matches
+    fclose(fp);  // ensure you close the file after writing
+}
+#endif
\ No newline at end of file
diff -r 5494a0fb3a33 -r 463abe5f5135 Joystick.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Joystick.h	Thu May 05 09:18:01 2016 +0000
@@ -0,0 +1,92 @@
+/**
+@file Joystick.h
+@brief Header file containing functions prototypes, defines and global variables for constructing joystick.
+@brief Example code of how to read a joystick with slightly changed for the game
+@https://www.sparkfun.com/products/9032
+@author Craig A. Evans
+@date 7 March 2015
+*/
+
+#ifndef JOYSTICK_H
+#define JOYSTICK_H
+
+#define DIRECTION_TOLERANCE 0.25
+
+/**
+Joystick vertical direction
+@brief Analog input for joystick to send vertical directions data
+*/
+AnalogIn yPot(PTB2);
+/**
+Joystick horizontal direction
+@brief Analog input for joystick to send horizontal direction data
+*/
+AnalogIn xPot(PTB3);
+
+//! create enumerated type (0,1,2,3 etc. for direction)
+//! could be extended for diagonals etc.
+enum DirectionName {
+    UP,
+    DOWN,
+    LEFT,
+    RIGHT,
+    CENTRE,
+    UNKNOWN
+};
+//! struct for Joystick
+typedef struct JoyStick Joystick;
+struct JoyStick {
+    double x;    // current x value
+    double x0;   // 'centred' x value
+    double y;    // current y value
+    double y0;   // 'centred' y value
+    int button; // button state (assume pull-down used, so 1 = pressed, 0 = unpressed)
+    DirectionName direction;  // current direction
+};
+//! create struct variable
+Joystick joystick;
+/**
+Read default positions of the joystick to calibrate later readings
+*/
+void calibrateJoystick();
+/**
+Update the current position of joystick
+*/
+void updateJoystick();
+
+/////////////////////////////////////////////////
+/// Function Definitions
+/////////////////////////////////////////////////
+
+// read default positions of the joystick to calibrate later readings
+void calibrateJoystick()
+{
+    // must not move during calibration
+    joystick.x0 = xPot;  // initial positions in the range 0.0 to 1.0 (0.5 if centred exactly)
+    joystick.y0 = yPot;
+}
+
+void updateJoystick()
+{
+    // read current joystick values relative to calibrated values (in range -0.5 to 0.5, 0.0 is centred)
+    joystick.x = xPot - joystick.x0;
+    joystick.y = yPot - joystick.y0;
+
+    // calculate direction depending on x,y values
+    // tolerance allows a little lee-way in case joystick not exactly in the stated direction
+    if ( fabs(joystick.y) < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) {
+        joystick.direction = CENTRE;
+    } else if ( joystick.y < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) {
+        joystick.direction = UP;
+    } else if ( joystick.y > DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) {
+        joystick.direction = DOWN;
+    } else if ( joystick.x < DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) {
+        joystick.direction = RIGHT;
+    } else if ( joystick.x > DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) {
+        joystick.direction = LEFT;
+    } else {
+        joystick.direction = UNKNOWN;
+    }
+}
+
+#endif
\ No newline at end of file
diff -r 5494a0fb3a33 -r 463abe5f5135 Patterns.h
--- a/Patterns.h	Sun May 01 23:09:33 2016 +0000
+++ b/Patterns.h	Thu May 05 09:18:01 2016 +0000
@@ -1,9 +1,27 @@
+/**
+@file Patterns.h
+@brief Header file containing member functions and variables
+@brief Header file patterns pixel settings and funtion to get specific pattern pixel setting
+@brief Revision 1.0.
+@author JIANWEI CHEN
+@date   May 2016
+*/
+
 #ifndef PATTERNS_H
 #define PATTERNS_H
+
+
 class Patterns
 {
 public:
-
+    /** Get pattern pixel setting
+    *
+    * @param type - pattern type (0~6)
+    * @param rotation - pattern rotation (0~3)
+    * @param y - pattern y co-ordinate  (0~6)
+    * @param x - pattern x co-ordinate (0~6)
+    * @note (x,y) is the top left corner pixel of a 6x6 square
+    */
     int getPatterns(int type, int rotation, int y, int x);
 
 private:
diff -r 5494a0fb3a33 -r 463abe5f5135 SDFileSystem.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDFileSystem.lib	Thu May 05 09:18:01 2016 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/SDFileSystem/#7b35d1709458
diff -r 5494a0fb3a33 -r 463abe5f5135 main.cpp
--- a/main.cpp	Sun May 01 23:09:33 2016 +0000
+++ b/main.cpp	Thu May 05 09:18:01 2016 +0000
@@ -1,577 +1,71 @@
 #include "mbed.h"
 #include "Patterns.h"
 #include "N5110.h"
-
-#define DIRECTION_TOLERANCE 0.05
-
-//VCC, SCE, RST, D/C, MOSI,SCLK, LED
-N5110 lcd(PTE26,PTA0,PTC4,PTD0,PTD2,PTD1,PTC3);
-AnalogIn yPot(PTB2);
-AnalogIn xPot(PTB3);
-DigitalIn button(PTB11);
-Patterns patterns;
-
-Ticker game;
-void game_isr();
-volatile int g_game_flag = 0;
-
-void drawPattern(int type,int rotation,int x,int y,int fill); // draw pattern at (x,y), fill = 0 white, fill = 1 black
-
-void left_collisionDetect();
-int left_collision_flag = 0;
-
-void right_collisionDetect();
-int right_collision_flag = 0;
-
-void bottom_collisionDetect();
-int bottom_collision_flag = 0;
-
-void top_collisionDetect();
-int top_collision_flag = 0;
-
-void rotation_collisionDetect();
-int rotation_collision_flag = 0;
-
-void fastmove_bottom_collisionDetect();
-int fastmove_bottom_collision_flag = 0;
-
-struct Position {
-    float x;
-    float y;
-    int type;
-    int rotation;
-};
-typedef struct Position position;
-
-position pos;
-
-void init_game();
-int typeArray[100];
-int rotationArray[100];
-
-int pattern_buffer[6][6];
-void get_pattern(int type, int rotatin);
-
-void scan();
-int buffer[84][48];
-
-// create enumerated type (0,1,2,3 etc. for direction)
-// could be extended for diagonals etc.
-enum DirectionName {
-    UP,
-    DOWN,
-    LEFT,
-    RIGHT,
-    CENTRE,
-    UNKNOWN
-};
-// struct for Joystick
-typedef struct JoyStick Joystick;
-struct JoyStick {
-    double x;    // current x value
-    double x0;   // 'centred' x value
-    double y;    // current y value
-    double y0;   // 'centred' y value
-    int button; // button state (assume pull-down used, so 1 = pressed, 0 = unpressed)
-    DirectionName direction;  // current direction
-};
-// create struct variable
-Joystick joystick;
-void calibrateJoystick();
-void updateJoystick();
-
-void cancelLine();// if one line is filled, cancel it and add the score
-int score=0;
-
-void finishAnimation();
-
-int xOld;
-int typeCount = 0;
-int nextTypeCount;
+#include "SDFileSystem.h"
+#include "Joystick.h"
+#include "Game.h"
+#include "main.h"
 
 int main()
 {
-    wait(2.0);  // short delay for power to settle
-    lcd.init();
-    lcd.normalMode();      // normal colour mode
-    lcd.setBrightness(1.0); // put LED backlight on 100%
-    init_game();
-    game.attach(&game_isr,0.2);
-    lcd.refresh();
-    calibrateJoystick();
-
-    while (1) {
+    init();
+    while(1) {
+        if(g_menuTimer_flag) {
+            g_menuTimer_flag=0;
 
-        if(g_game_flag==1) {
-            g_game_flag = 0;
-            pos.type = typeArray[typeCount];
-            nextTypeCount=typeCount+1;
-            if (nextTypeCount>99) {
-                nextTypeCount=0;
-            }
-            drawPattern(typeArray[nextTypeCount],0,55,41,1);// draw next pattern
-            if (pos.y >= -5) { // clear previous pattern
-                drawPattern(pos.type,pos.rotation,xOld,pos.y-1,0);
-            }
-            updateJoystick();
-            top_collisionDetect();
-            if (top_collision_flag == 1) {
-                finishAnimation();
+            if (g_button_flag) {// if button pressed, go to next menu according current state and pointer position input
+                g_button_flag=0;
+                state=fsm[state].nextState[pointer_position];
                 lcd.clear();
-                char scoreBuffer[14];
-                sprintf(scoreBuffer,"%d",score);
-                lcd.printString("SCORE IS: ",10,2);
-                lcd.printString(scoreBuffer,35,3);
-                lcd.refresh();
-                break;
-            }
-            switch(joystick.direction) {
-                case UP:
-                    rotation_collisionDetect();
-                    if(rotation_collision_flag == 0) {
-                        pos.rotation++;
-                        if (pos.rotation>3) {
-                            pos.rotation=0;
-                        }
-                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
-                    } else {// if collision
-                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
-                    }
-                    break;
-                case DOWN:
-                    fastmove_bottom_collisionDetect();
-                    if (fastmove_bottom_collision_flag == 0) {
-                        pos.y +=4;
-                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
-                    } else {
-                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
-                    }
-                    break;
-                case RIGHT:
-                    right_collisionDetect();
-                    if( right_collision_flag == 0) {
-                        pos.x +=2;
-                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
-                    } else {
-                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
-                        right_collision_flag = 0;
-                    }
-                    break;
-                case LEFT:
-                    left_collisionDetect();
-                    if( left_collision_flag == 0) {
-                        pos.x -=2;
-                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
-                    } else {
-                        drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
-                        left_collision_flag = 0;
-                    }
-
-                    break;
-                case CENTRE:
-                    drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
-                    break;
-                case  UNKNOWN:
-                    drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);
-                    break;
-            }
-
-            xOld = pos.x;
-            bottom_collisionDetect();
-            if (bottom_collision_flag == 0) {
-                pos.y++;
-            } else {
-                drawPattern(pos.type,pos.rotation,pos.x,pos.y,1);// fix pattern
-                cancelLine();
-                pos.x = 10;
-                pos.y = -6;
-                pos.rotation=0;
-                drawPattern(typeArray[nextTypeCount],pos.rotation,55,41,0);// clear the old next pattern
-                typeCount ++;
-                if (typeCount >99) {
-                    typeCount = 0;
-                }
             }
 
-        }
-        lcd.refresh();
-    }
-
-}
-
-void init_game()
-{
-    pos.x = 10;
-    pos.y = -6;
-    pos.rotation=0;
-    for(int i=0; i<=99; i++) {
-        typeArray[i] = rand()%7;
-        rotationArray[i] = rand()%5;
-    }
-    lcd.drawLine(30,0,30,47,1);
-    lcd.printString("Level:",42,0);
-    lcd.printString("easy",42,1);
-    lcd.printString("Score:",42,2);
-    lcd.printString("0",42,3);
-    lcd.printString("Next:",42,4);
-
-}
-
-void get_pattern(int type, int rotation)
-{
-    for(int i=0; i<=5; i++) {
-        for(int j=0; j<=5; j++) {
-            pattern_buffer[i][j] = patterns.getPatterns(type,rotation,j,i);  // return pattern[type][rotation][y][x];
-        }
-    }
-}
-
-void scan()
-{
-    for (int i=0; i<=83; i++) {
-        for (int j=0; j<=47; j++) {
-            if(lcd.getPixel(i,j)) {
-                buffer[i][j] = 1;
-            } else {
-                buffer[i][j] = 0;
-            }
-        }
-    }
-}
-
-
-void drawPattern(int type,int rotation,int x,int y,int fill)
-{
-    get_pattern(type,rotation);
-    for(int i=x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square
-        for(int j=y; j <= y+5; j++) {
-            if (j>=0) {
-                if(pattern_buffer[i-x][j-y]==1) {
-                    if (fill==0) {
-                        if (j<=47 && i>=0) {
-                            lcd.clearPixel(i,j);
-                        }
-                    } else if (fill==1) {
-                        if (j<=47 && i>=0) {
-                            lcd.setPixel(i,j);
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
-
-void left_collisionDetect()
-{
-    int left_boundary[6][6];
-    get_pattern(pos.type,pos.rotation);
-
-    // get the left boundary pattern
-    for (int j=0; j<=5; j++) { //
-        for (int i=0; i<=5; i++) {
-            if (pattern_buffer[i][j]==1) {
-                left_boundary[i][j]=1;
-                for(int k=i+1; k<=5; k++) {
-                    left_boundary[k][j] = 0;
-                }
-                break;
-            } else {
-                left_boundary[i][j]=0;
-            }
-        }
-    }
-
-    //check left collision
-    int x = pos.x;
-    int y = pos.y;
-    if (x<0) {
-        left_collision_flag = 1;
-    } else {
-        for(int i=x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square
-            for(int j=y; j <= y+5; j++) {
-                if(left_boundary[i-x][j-y]==1) {
-                    if(i == 0) {
-                        left_collision_flag = 1;
-                        break;
-                    } else if (lcd.getPixel(i-1,j)) {
-                        left_collision_flag = 1;
-                        break;
-                    } else {
-                        left_collision_flag = 0;
-                    }
-                }
-            }
-            if (left_collision_flag == 1) {
-                break;
-            }
-        }
-    }
-}
-
-
-void right_collisionDetect()
-{
-    int right_boundary[6][6];
-    get_pattern(pos.type,pos.rotation);
-    // get the left boundary pattern
-    for (int j=0; j<=5; j++) {
-        for (int i=5; i>=0; i--) {
-            if (pattern_buffer[i][j]==1) {
-                right_boundary[i][j]=1;
-                for(int k=i-1; k>=0; k--) {
-                    right_boundary[k][j] = 0;
-                }
-                break;
-            } else {
-                right_boundary[i][j]=0;
+            switch(state) {
+                case 0: // main menu
+                    pointer();
+                    red_led=0;
+                    green_led=0;
+                    lcd.printString("Tetis Game",10,1);
+                    lcd.printString("START",25,3);
+                    lcd.printString("SCORE",25,4);
+                    lcd.refresh();
+                    break;
+                case 1: // game level choosing menu
+                    pointer();
+                    red_led=0;
+                    green_led=0;
+                    lcd.printString("Game Level",10,1);
+                    lcd.printString("EASY",25,3);
+                    lcd.printString("HARD",25,4);
+                    lcd.printString("Back",60,5);
+                    lcd.refresh();
+                    break;
+                case 2: // highest score menu
+                    red_led=0;
+                    green_led=0;
+                    lcd.printString("Highest Score:",1,1);
+                    int top_score;
+                    top_score=read_score_SD();
+                    char score[14];
+                    sprintf(score,"%d",top_score);
+                    lcd.printString(score,30,3);
+                    lcd.printString("Press Button",0,4);
+                    lcd.printString("To Exit",0,5);
+                    lcd.refresh();
+                    break;
+                case 3: // easy game menu
+                    init_game();
+                    game.attach(&game_isr,0.2);
+                    lcd.printString("easy",42,1);
+                    tetis_game();
+                    break;
+                case 4: // hard game menu
+                    init_game();
+                    game.attach(&game_isr,0.1);
+                    lcd.printString("hard",42,1);
+                    tetis_game();
+                    break;
             }
         }
-    }
-
-    //check left collision
-    int x = pos.x;
-    int y = pos.y;
-    for(int i = x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square
-        for(int j=y; j <= y+5; j++) {
-            if(right_boundary[i-x][j-y]==1) {
-                if(j>=0) {
-                    if(i >= 29) {
-                        right_collision_flag = 1;
-                        break;
-                    } else if (lcd.getPixel(i+1,j)) {
-                        right_collision_flag = 1;
-                        break;
-                    } else {
-                        right_collision_flag = 0;
-                    }
-                }
-            }
-        }
-        if (right_collision_flag == 1) {
-            break;
-        }
-
-    }
-}
-
-void bottom_collisionDetect()
-{
-    int bot_boundary[6][6];
-    get_pattern(pos.type,pos.rotation);
-    // get the left boundary pattern
-    for (int i=0; i<=5; i++) {
-        for (int j=5; j>=0; j--) {
-            if (pattern_buffer[i][j]==1) {
-                bot_boundary[i][j]=1;
-                for(int k=j-1; k>=0; k--) {
-                    bot_boundary[i][k] = 0;
-                }
-                break;
-            } else {
-                bot_boundary[i][j]=0;
-            }
-        }
-    }
-
-    //check left collision
-    int x = pos.x;
-    int y = pos.y;
-    for(int i = x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square
-        for(int j=y+5; j >= y; j--) {
-            if (j>=-1) {
-                if(bot_boundary[i-x][j-y]==1) {
-                    if(j >= 47) {
-                        bottom_collision_flag = 1;
-                        break;
-                    } else if (lcd.getPixel(i,j+1)) {
-                        bottom_collision_flag = 1;
-                        break;
-                    } else {
-                        bottom_collision_flag = 0;
-                    }
-                }
-            } else {
-                bottom_collision_flag = 0;
-            }
-        }
-        if( bottom_collision_flag == 1) {
-            break;
-        }
-    }
-}
-
-void rotation_collisionDetect()
-{
-    int rotation = pos.rotation+1;
-    if (rotation>3) {
-        rotation=0;
-    }
-    get_pattern(pos.type,rotation);
-
-    //check
-    int x = pos.x;
-    int y = pos.y;
-    for(int i = x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square
-        for(int j=y; j <= y+5; j++) {
-            if(pattern_buffer[i-x][j-y]==1) {
-                if(i<0) {
-                    rotation_collision_flag = 1;
-                } else if(lcd.getPixel(i,j)) {
-                    rotation_collision_flag = 1;
-                    break;
-                } else {
-                    rotation_collision_flag = 0;
-                }
-            }
-        }
-        if (rotation_collision_flag == 1) {
-            break;
-        }
-    }
-}
-
-void top_collisionDetect()
-{
-    if (pos.y==-6) {
-        bottom_collisionDetect();
-        if (bottom_collision_flag == 1) {
-            top_collision_flag = 1;
-        } else {
-            top_collision_flag = 0;
-        }
+        sleep();
     }
 }
-
-void fastmove_bottom_collisionDetect()
-{
-    int bot_boundary[6][6];
-    get_pattern(pos.type,pos.rotation);
-    // get the left boundary pattern
-    for (int i=0; i<=5; i++) {
-        for (int j=5; j>=0; j--) {
-            if (pattern_buffer[i][j]==1) {
-                bot_boundary[i][j]=1;
-                for(int k=j-1; k>=0; k--) {
-                    bot_boundary[i][k] = 0;
-                }
-                break;
-            } else {
-                bot_boundary[i][j]=0;
-            }
-        }
-    }
-
-    //check left collision
-    int x = pos.x;
-    int y = pos.y;
-    for(int i = x; i <= x+5; i++) { // (x,y) is the left top point of a 6*6 square
-        for(int j=y+5; j >= y; j--) {
-            if (j>=-1) {
-                if(bot_boundary[i-x][j-y]==1) {
-                    if(j >= 42) {
-                        fastmove_bottom_collision_flag = 1;
-                        break;
-                    } else if (lcd.getPixel(i,j+4)) {
-                        fastmove_bottom_collision_flag = 1;
-                        break;
-                    } else {
-                        fastmove_bottom_collision_flag = 0;
-                    }
-                }
-            } else {
-                fastmove_bottom_collision_flag = 0;
-            }
-        }
-        if( fastmove_bottom_collision_flag == 1) {
-            break;
-        }
-    }
-}
-
-void game_isr()
-{
-    g_game_flag = 1;
-}
-
-// read default positions of the joystick to calibrate later readings
-void calibrateJoystick()
-{
-    button.mode(PullDown);
-    // must not move during calibration
-    joystick.x0 = xPot;  // initial positions in the range 0.0 to 1.0 (0.5 if centred exactly)
-    joystick.y0 = yPot;
-}
-
-void updateJoystick()
-{
-    // read current joystick values relative to calibrated values (in range -0.5 to 0.5, 0.0 is centred)
-    joystick.x = xPot - joystick.x0;
-    joystick.y = yPot - joystick.y0;
-    // read button state
-    joystick.button = button;
-
-    // calculate direction depending on x,y values
-    // tolerance allows a little lee-way in case joystick not exactly in the stated direction
-    if ( fabs(joystick.y) < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) {
-        joystick.direction = CENTRE;
-    } else if ( joystick.y < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) {
-        joystick.direction = UP;
-    } else if ( joystick.y > DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) {
-        joystick.direction = DOWN;
-    } else if ( joystick.x < DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) {
-        joystick.direction = RIGHT;
-    } else if ( joystick.x > DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) {
-        joystick.direction = LEFT;
-    } else {
-        joystick.direction = UNKNOWN;
-    }
-
-}
-
-void cancelLine()
-{
-    // int linePattern[30][2]; //the pixel setting for one line(30x2 square)
-    int count;
-    for(int j=0; j<=46; j+=2) {
-        for(int i=0; i<=29; i++) {
-            if (lcd.getPixel(i,j)==0||lcd.getPixel(i,j+1)==0) {
-                count=0;
-                break;
-            } else if (lcd.getPixel(i,j)&&lcd.getPixel(i,j+1)) {
-                count++;
-            }
-        }
-        if(count==30) { // one line is filled
-            count=0;
-            lcd.drawRect(0,j,29,1,2); //clear the line
-            score+=10;  // add the score
-            //print the score
-            char scoreBuffer[14];
-            sprintf(scoreBuffer,"%d",score);
-            lcd.printString(scoreBuffer,42,3);
-            scan();
-            // move the patterns upon the line down for 2 pixels' hight
-            for (int x=0; x<=29; x++) {
-                for (int y=j; y>=0; y--) {
-                    if (buffer[x][y]) {
-                        lcd.clearPixel(x,y);
-                        lcd.setPixel(x,y+2);
-                    }
-                }
-            }
-        }
-    }
-}
-
-void finishAnimation()
-{
-    for (int j=47; j>=0; j--) {
-        lcd.drawRect(0,j,29,1,1);
-        wait(0.05);
-        lcd.refresh();
-    }
-}
-
-
-
diff -r 5494a0fb3a33 -r 463abe5f5135 main.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.h	Thu May 05 09:18:01 2016 +0000
@@ -0,0 +1,186 @@
+/**
+@file main.h
+@brief Header file containing functions prototypes, defines and global variables for menu and pointer
+@brief Menu is construct using finit state mechine. 
+@brief The input for finit state mechine is the positer position. 
+@brief Revision 1.0. 
+@author JIANWEI CHEN
+@date   May 2016
+*/
+#ifndef MAIN_H
+#define MAIN_H
+
+#include "mbed.h"
+//        VCC, SCE, RST, D/C, MOSI,SCLK, LED
+N5110 lcd(PTE26,PTA0,PTC4,PTD0,PTD2,PTD1,PTC3);
+//                MOSI, MISO, SCK, CS
+SDFileSystem sd(PTE3, PTE1, PTE2, PTE4, "sd");
+
+FILE *fp; /*!< File pointer */
+
+DigitalOut red_led(PTA1);
+DigitalOut green_led(PTC2);
+InterruptIn button(PTB18);
+PwmOut buzzer (PTA2);
+
+////////////////////////////////////////////////////////
+// Variables
+////////////////////////////////////////////////////////
+/**
+Create ticker object for menu
+@brief ticker to control the speed of updating the menu
+*/
+Ticker menuTimer;
+
+volatile int g_menuTimer_flag = 0; /*!< Flag for menu ticker */
+volatile int g_button_flag = 0; /*!< Flag for button interrupt */
+
+/**State of menu
+@brief Variable control the state of menu
+@note state 0 - main menu
+@note state 1 - game level choosing menu
+@note state 2 - show highest score menu
+@note state 3 - game with easy level
+@note state 4 - game with hard level
+*/
+int state=0;
+
+int pointer_position=0;/*!< Variable control the position of pointer */
+
+/**struct for state
+*/
+struct State {
+    int nextState[3];  // array of next states
+};
+typedef const struct State STyp;
+
+STyp fsm[5] = {
+    {1,2,0}, // states chosen according to inputs(pointer position)
+    {3,4,0},
+    {0,0,0},
+    {0,0,0},
+    {0,0,0}
+};
+
+//////////////////////////////////////////////////////////////////
+// Functions
+//////////////////////////////////////////////////////////////////
+
+/**
+Menu isr function
+*/
+void menuTimer_isr();
+
+/**
+Initialise the program and lcd, mbed initial settings
+*/
+void init();
+
+/**
+Button interrupt isr function
+*/
+void button_isr();
+
+/**Drawing the pointer at (x,y)
+@brief Drawing the pointer image at (x,y) according to inputs
+@param x - x co-ordinate of lcd
+@param y - y co-ordinate of lcd
+@param fill - fill = 0 white, fill = 1 black
+*/
+void pointer_image(int x,int y,int fill);//0-white 1-black
+
+/** Move the pointer
+@brief Function to control the pointer according to joystick
+*/
+void pointer();
+
+
+/////////////////////////////////////////////////
+/// Function Definitions
+/////////////////////////////////////////////////
+void menuTimer_isr()
+{
+    g_menuTimer_flag = 1;
+}
+
+
+void button_isr()
+{
+    g_button_flag=1;
+}
+
+
+void pointer()
+{
+    updateJoystick(); // get joystick direction
+    if (joystick.direction==UP) {
+        if(pointer_position==0) { // pointer at the top
+            pointer_position=0;
+        } else {
+            pointer_position--;
+        }
+    } else if(joystick.direction==DOWN) {
+        if(pointer_position==1&&(state!=1)) { //only game level choosing menu have 3 pointer positions
+            pointer_position=1;
+        } else if (pointer_position==2&&(state==1)) {
+            pointer_position=2;
+        } else {
+            pointer_position++;
+        }
+    }
+
+    if(pointer_position==0) {
+        pointer_image(10,27,1); // draw pointer
+        pointer_image(10,35,0); // clear pointer at other positions
+        pointer_image(10,43,0);
+    } else if(pointer_position==1) {
+        pointer_image(10,27,0);
+        pointer_image(10,35,1);
+        pointer_image(10,43,0);
+    } else if(pointer_position==2) {
+        pointer_image(10,35,0);
+        pointer_image(10,43,1);
+    }
+
+}
+
+
+void pointer_image(int x,int y,int fill)
+{
+    if(fill==0) {// draw white pointer
+        lcd.drawLine(x,y,x-4,y+2,0);
+        lcd.drawLine(x,y,x-4,y-2,0);
+    } else { // draw black pointer
+        lcd.drawLine(x,y,x-4,y-2,1);
+        lcd.drawLine(x,y,x-4,y+2,1);
+    }
+}
+
+
+void init(){
+    wait(2.0);  // short delay for power to settle
+    // initialise sd card
+    fp = fopen("/sd/topscore.txt", "r");
+    fclose(fp);  // ensure you close the file after reading
+    lcd.init(); // initialise lcd
+    lcd.normalMode();      // normal colour mode
+    lcd.setBrightness(1.0); // put LED backlight on 100%
+    
+    lcd.printString("Calibrating",0,0);
+    lcd.printString("Joystick........",0,1);
+    lcd.printString("PLEASE DO NOT",0,3);
+    lcd.printString("MOVE JOYSTICK.....",0,4);
+    lcd.refresh();
+    calibrateJoystick();
+    wait(4.0);
+    
+    lcd.clear();
+    lcd.refresh();
+    button.mode(PullDown);
+    red_led=0;
+    green_led=0;
+    button.fall(&button_isr);
+    menuTimer.attach(&menuTimer_isr,0.1); // attach menu ticker
+    buzzer.period(1.0/4000.0);  // set buzzer period to 4 kKz
+}
+#endif
\ No newline at end of file
diff -r 5494a0fb3a33 -r 463abe5f5135 mbed.bld
--- a/mbed.bld	Sun May 01 23:09:33 2016 +0000
+++ b/mbed.bld	Thu May 05 09:18:01 2016 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/mbed/builds/87f2f5183dfb
\ No newline at end of file
+http://mbed.org/users/mbed_official/code/mbed/builds/aae6fcc7d9bb
\ No newline at end of file