This is a remake of tetris game for mbed. Please see detail here http://developer.mbed.org/users/sucrelv/notebook/tetris-game-on-mbed

Dependencies:   4DGL-uLCD-SE PinDetect SDFileSystem mbed-rtos mbed wave_player

Revision:
0:3b5e97ab5884
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Oct 21 15:10:36 2014 +0000
@@ -0,0 +1,480 @@
+#include "mbed.h"
+#include "Game.h"
+#include "PinDetect.h"
+#include "Speaker.h"
+#include "TextLCD.h"
+#include "Shiftbrite.h"
+#include "SDFileSystem.h"
+#include "wave_player.h"
+#include "rtos.h"
+
+uLCD_4DGL uLCD(p28, p27, p29);
+TextLCD textLCD(p26, p25, p24, p23, p22, p15); 
+Speaker mySpeaker(p21);
+Shiftbrite myShiftbrite(p9, p10, p11, p12, p13);
+SDFileSystem sd(p5, p6, p7, p8, "sd"); //SD card
+Serial pc(USBTX, USBRX);
+
+PinDetect LEFT_KEY(p16);
+PinDetect RIGHT_KEY(p19);
+PinDetect ROTATE_KEY(p17);
+PinDetect DOWN_KEY(p30);
+
+int SinglePiecePoints = 50;
+int LineClearPoints = 200;
+int key_input = 0;
+bool gameStarted = false;
+void input_left()
+{
+    if(!gameStarted)
+    {   gameStarted=true;
+        return;
+    }
+    key_input = 1;
+    mySpeaker.PlayNote(400.0,0.05,0.025);
+    mySpeaker.PlayNote(500.0,0.05,0.025);
+}
+
+void input_right()
+{
+    if(!gameStarted)
+    {   gameStarted=true;
+        return;
+    }
+    key_input = 2;
+    mySpeaker.PlayNote(400.0,0.05,0.025);
+    mySpeaker.PlayNote(500.0,0.05,0.025);
+}
+
+void input_rotate()
+{
+    if(!gameStarted)
+    {   gameStarted=true;
+        return;
+    }
+    key_input = 3;
+    mySpeaker.PlayNote(600.0,0.05,0.025);
+    mySpeaker.PlayNote(700.0,0.05,0.025);
+    mySpeaker.PlayNote(800.0,0.05,0.025);
+    mySpeaker.PlayNote(900.0,0.05,0.025);
+}
+
+void input_down()
+{
+    if(!gameStarted)
+    {   gameStarted=true;
+        return;
+    }
+    key_input=4;
+    mySpeaker.PlayNote(500.0,0.05,0.025);
+    mySpeaker.PlayNote(1500.0,0.05,0.025);
+    mySpeaker.PlayNote(500.0,0.05,0.025);
+    mySpeaker.PlayNote(1500.0,0.05,0.025);
+}
+
+void clear_board()
+{
+    uLCD.filled_rectangle(20,0,79,128,0);
+}
+
+void clear_next_piece()
+{
+    uLCD.filled_rectangle(92,20,122,50,0);
+}
+
+void UpdateGameStatus(int points,int lines)
+{
+    textLCD.locate(7,0);
+    textLCD.printf("%d",points);
+    textLCD.locate(13,1);
+    textLCD.printf("%d",lines);
+}
+
+void FlashLight(void const *args)
+{
+    myShiftbrite.RGB(0,0,0);
+    myShiftbrite.RGB(0,0,0);
+        
+    myShiftbrite.RGB(0,0,42);
+    myShiftbrite.RGB(0,0,42);
+    Thread::wait(100);
+        
+        
+    myShiftbrite.RGB(0,0,0);
+    myShiftbrite.RGB(0,42,0);
+    Thread::wait(100);
+        
+    myShiftbrite.RGB(0,0,42);
+    myShiftbrite.RGB(0,0,42);
+    Thread::wait(100);
+        
+    myShiftbrite.RGB(0,0,0);
+    myShiftbrite.RGB(0,0,0);    
+}
+
+void GameOverLight(void const *args)
+{
+    
+    myShiftbrite.RGB(0,0,0);
+    myShiftbrite.RGB(0,0,0);
+        
+    myShiftbrite.RGB(0,0,200);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,0);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,200);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,0);  
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,200);
+    Thread::wait(100); 
+    myShiftbrite.RGB(0,0,0);  
+    Thread::wait(100); 
+    myShiftbrite.RGB(0,0,200);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,0);  
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,200);
+    Thread::wait(100); 
+    myShiftbrite.RGB(0,0,0);
+    Thread::wait(100); 
+    myShiftbrite.RGB(0,0,200);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,0);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,200);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,0);  
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,200);
+    Thread::wait(100); 
+    myShiftbrite.RGB(0,0,0);  
+    Thread::wait(100); 
+    myShiftbrite.RGB(0,0,200);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,0);  
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,200);
+    Thread::wait(100); 
+    myShiftbrite.RGB(0,0,0); 
+}
+
+void GameStartLight(void const *args)
+{
+    
+    myShiftbrite.RGB(0,0,0);
+    myShiftbrite.RGB(0,0,0);
+        
+    myShiftbrite.RGB(0,200,0);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,0);
+    myShiftbrite.RGB(0,0,0);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,200,0);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,0); 
+    myShiftbrite.RGB(0,0,0); 
+    Thread::wait(100);
+    myShiftbrite.RGB(0,200,0);
+    Thread::wait(100); 
+    myShiftbrite.RGB(0,0,0); 
+    myShiftbrite.RGB(0,0,0); 
+    Thread::wait(100); 
+    myShiftbrite.RGB(0,200,0);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,0,0);  
+    myShiftbrite.RGB(0,0,0);
+    Thread::wait(100);
+    myShiftbrite.RGB(0,200,0);
+    Thread::wait(100); 
+    myShiftbrite.RGB(0,0,0);
+    myShiftbrite.RGB(0,0,0);
+    
+}
+
+void PlayStartSound()
+{
+    mySpeaker.PlayNote(500.0,0.05,0.025);
+    mySpeaker.PlayNote(600.0,0.05,0.025);
+    mySpeaker.PlayNote(700.0,0.05,0.025);
+    mySpeaker.PlayNote(800.0,0.05,0.025);
+    mySpeaker.PlayNote(900.0,0.05,0.025);
+    mySpeaker.PlayNote(1000.0,0.05,0.025);
+    mySpeaker.PlayNote(1100.0,0.05,0.025);
+    mySpeaker.PlayNote(1200.0,0.05,0.025);
+    mySpeaker.PlayNote(600.0,0.05,0.025);
+    mySpeaker.PlayNote(700.0,0.05,0.025);
+    mySpeaker.PlayNote(800.0,0.05,0.025);
+    mySpeaker.PlayNote(900.0,0.05,0.025);
+    mySpeaker.PlayNote(1000.0,0.05,0.025);
+    mySpeaker.PlayNote(1100.0,0.05,0.025);
+    mySpeaker.PlayNote(1200.0,0.05,0.025);
+    mySpeaker.PlayNote(1300.0,0.05,0.025);
+    mySpeaker.PlayNote(700.0,0.05,0.025);
+    mySpeaker.PlayNote(800.0,0.05,0.025);
+    mySpeaker.PlayNote(900.0,0.05,0.025);
+    mySpeaker.PlayNote(1000.0,0.05,0.025);
+    mySpeaker.PlayNote(1100.0,0.05,0.025);
+    mySpeaker.PlayNote(1200.0,0.05,0.025);
+    mySpeaker.PlayNote(1300.0,0.05,0.025);
+    mySpeaker.PlayNote(1400.0,0.05,0.025);
+}
+
+void PlayOverSound()
+{
+    mySpeaker.PlayNote(1400.0,0.05,0.025);
+    mySpeaker.PlayNote(1300.0,0.05,0.025);
+    mySpeaker.PlayNote(1200.0,0.05,0.025);
+    mySpeaker.PlayNote(1100.0,0.05,0.025);
+    mySpeaker.PlayNote(1000.0,0.05,0.025);
+    mySpeaker.PlayNote(900.0,0.05,0.025);
+    mySpeaker.PlayNote(800.0,0.05,0.025);
+    mySpeaker.PlayNote(700.0,0.05,0.025);
+    mySpeaker.PlayNote(1300.0,0.05,0.025);
+    mySpeaker.PlayNote(1200.0,0.05,0.025);
+    mySpeaker.PlayNote(1100.0,0.05,0.025);
+    mySpeaker.PlayNote(1000.0,0.05,0.025);
+    mySpeaker.PlayNote(900.0,0.05,0.025);
+    mySpeaker.PlayNote(800.0,0.05,0.025);
+    mySpeaker.PlayNote(700.0,0.05,0.025);
+    mySpeaker.PlayNote(600.0,0.05,0.025);
+    mySpeaker.PlayNote(1200.0,0.05,0.025);
+    mySpeaker.PlayNote(1100.0,0.05,0.025);
+    mySpeaker.PlayNote(1000.0,0.05,0.025);
+    mySpeaker.PlayNote(900.0,0.05,0.025);
+    mySpeaker.PlayNote(800.0,0.05,0.025);
+    mySpeaker.PlayNote(700.0,0.05,0.025);
+    mySpeaker.PlayNote(600.0,0.05,0.025);
+    mySpeaker.PlayNote(500.0,0.05,0.025);
+}
+
+void PlayClearSound()
+{
+    mySpeaker.PlayNote(900.0,0.2,0.025);
+    mySpeaker.PlayNote(1000.0,0.2,0.025);
+    mySpeaker.PlayNote(1100.0,0.2,0.025);
+    mySpeaker.PlayNote(1000.0,0.2,0.025);
+    mySpeaker.PlayNote(9000.0,0.2,0.025);
+}
+
+int RandomGen(char range)
+{
+    pc.printf("%c",range);
+    while(!pc.readable()) wait(0.5);
+    char buffer[4];
+    pc.gets(buffer,4);
+    int i = buffer[0]-'0';
+    return i;
+}
+
+int main()
+{
+    //hardware setup
+    LEFT_KEY.mode(PullUp);
+    RIGHT_KEY.mode(PullUp);
+    ROTATE_KEY.mode(PullUp);
+    DOWN_KEY.mode(PullUp);
+    
+    LEFT_KEY.attach_deasserted(&input_left);
+    RIGHT_KEY.attach_deasserted(&input_right);
+    ROTATE_KEY.attach_deasserted(&input_rotate);
+    DOWN_KEY.attach_deasserted(&input_down);
+    
+    LEFT_KEY.setSampleFrequency();
+    RIGHT_KEY.setSampleFrequency();
+    ROTATE_KEY.setSampleFrequency();
+    DOWN_KEY.setSampleFrequency();
+    uLCD.baudrate(3000000);
+    
+    myShiftbrite.RGB(0,0,0);
+    myShiftbrite.RGB(0,0,0);
+    
+    sd.disk_initialize();
+    uLCD.media_init();
+    uLCD.set_sector_address(0x001D, 0x7801);
+    uLCD.display_image(0,0);
+    
+    textLCD.cls();
+    textLCD.locate(0,0);
+    textLCD.printf("Waiting for PC...");
+    pc.baud(9600);
+    pc.format(8,SerialBase::None,1);
+    pc.printf("0");
+    while(!pc.readable()) wait(0.5);
+    char buffer[4];
+    pc.gets(buffer,4);
+    
+    //wait for game start
+    textLCD.cls();
+    textLCD.locate(0,0);
+    textLCD.printf("TETRIS READY!!");
+    textLCD.locate(0,1);
+    textLCD.printf("PRESS ANY KEY...");
+    while(!gameStarted) wait(0.5);
+    PlayStartSound();
+    textLCD.cls();
+    textLCD.printf("Starting game   now...");
+    wait(2);
+    textLCD.cls();
+    textLCD.locate(0,0);
+    textLCD.printf("Points");
+    textLCD.locate(0,1);
+    textLCD.printf("Cleared Line");
+    Thread t1(GameStartLight);
+    //game classes init
+    bool isGameOver = false;
+    int mScreenHeight = 128;
+    Pieces mPieces;
+    Board mBoard (&mPieces, mScreenHeight);
+    int a = RandomGen('a');
+    int b = RandomGen('b');
+    int c = RandomGen('a');
+    int d = RandomGen('b');
+    Game mGame (&mBoard, &mPieces, mScreenHeight, &uLCD,a,b,c,d);
+
+
+    // ----- Main Loop -----
+    int prevX=0;
+    int prevY=0;
+    int prevPiece=-1;
+    int prevRot=0;
+    Timer timer;
+    timer.start();
+    key_input=0;
+    bool needErase = false;
+    uLCD.cls();
+    while (1)
+    {
+        if(isGameOver) 
+        {
+            wait(1);
+            continue;
+        }
+        // ----- Draw ----
+        if(needErase)
+        {
+            mGame.ErasePiece(prevX,prevY,prevPiece,prevRot);
+            needErase=false;
+        }
+        mGame.DrawScene();
+        
+        prevX=mGame.mPosX;
+        prevY=mGame.mPosY;
+        prevPiece=mGame.mPiece;
+        prevRot=mGame.mRotation;
+
+        // ----- Input -----
+        switch (key_input)
+        {
+            case (2): //right
+            {
+                if (mBoard.IsPossibleMovement (mGame.mPosX + 1, mGame.mPosY, mGame.mPiece, mGame.mRotation))
+                    {mGame.mPosX++;needErase=true;}
+                break;
+            }
+
+            case (1): //left
+            {
+                if (mBoard.IsPossibleMovement (mGame.mPosX - 1, mGame.mPosY, mGame.mPiece, mGame.mRotation))
+                    {mGame.mPosX--;needErase=true;}  
+                break;
+            }
+
+            case (4)://down
+            {
+                // Check collision from up to down
+                while (mBoard.IsPossibleMovement(mGame.mPosX, mGame.mPosY, mGame.mPiece, mGame.mRotation)) { mGame.mPosY++; }
+                needErase=true;
+                mBoard.StorePiece (mGame.mPosX, mGame.mPosY - 1, mGame.mPiece, mGame.mRotation);
+                mGame.AddPoints(SinglePiecePoints);
+                int linesDeleted = mBoard.DeletePossibleLines ();
+                if(linesDeleted>0)
+                {
+                    mGame.AddClearedLines(linesDeleted);
+                    mGame.AddPoints(LineClearPoints*linesDeleted);
+                    Thread t1(FlashLight);
+                    PlayClearSound();
+                    clear_board();
+                }
+                UpdateGameStatus(mGame.GetPoints(),mGame.GetClearedLines());
+
+                if (mBoard.IsGameOver())
+                {
+                    isGameOver=true;
+                    uLCD.cls();
+                    uLCD.media_init();
+                    uLCD.set_sector_address(0x001D, 0x7842);
+                    uLCD.display_image(0,0);
+                    Thread t2(GameOverLight);
+                    PlayOverSound();
+                    
+                }
+                
+                if(!isGameOver)
+                {
+                mGame.CreateNewPiece(RandomGen('a'),RandomGen('b'));
+                clear_next_piece();
+                }
+                break;
+            }
+
+            case (3)://rotate
+            {
+                if (mBoard.IsPossibleMovement (mGame.mPosX, mGame.mPosY, mGame.mPiece, (mGame.mRotation + 1) % 4))
+                    {mGame.mRotation = (mGame.mRotation + 1) % 4;needErase=true;}
+                break;
+            }
+            
+            case (0):{break;}
+        }
+        key_input = 0;
+        
+        // ----- Vertical movement -----
+
+        if(timer.read_ms()>WAIT_TIME)
+        {
+            needErase=true;
+            if(!isGameOver)
+            {
+                if (mBoard.IsPossibleMovement (mGame.mPosX, mGame.mPosY + 1, mGame.mPiece, mGame.mRotation))
+                {
+                    mGame.mPosY++;
+                }
+                else
+                {
+                    mBoard.StorePiece (mGame.mPosX, mGame.mPosY, mGame.mPiece, mGame.mRotation);
+                    mGame.AddPoints(SinglePiecePoints);
+                    int linesDeleted = mBoard.DeletePossibleLines ();
+                    if(linesDeleted>0)
+                    {
+                        mGame.AddClearedLines(linesDeleted);
+                        mGame.AddPoints(LineClearPoints*linesDeleted);
+                        Thread t1(FlashLight);
+                        PlayClearSound();
+                        clear_board();
+                    }
+                    UpdateGameStatus(mGame.GetPoints(),mGame.GetClearedLines());
+                        
+                    if (mBoard.IsGameOver())
+                    {
+                        isGameOver=true;
+                        uLCD.cls();
+                        uLCD.media_init();
+                        uLCD.set_sector_address(0x001D, 0x7842);
+                        uLCD.display_image(0,0);
+                        Thread t2(GameOverLight);
+                        PlayOverSound();
+                    }
+                    
+                    if(!isGameOver)
+                    {
+                    mGame.CreateNewPiece(RandomGen('a'),RandomGen('b'));
+                    clear_next_piece();
+                    }
+                }
+            }
+            timer.reset();
+        }
+            wait(0.1);
+    }
+}