Initial test

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

Files at this revision

API Documentation at this revision

Comitter:
rushib1
Date:
Tue Apr 28 02:13:45 2020 +0000
Parent:
4:c1da839b41b1
Commit message:
Commenting

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/main.cpp	Mon Apr 27 03:38:35 2020 +0000
+++ b/main.cpp	Tue Apr 28 02:13:45 2020 +0000
@@ -10,10 +10,25 @@
 #include <fstream>
 #include <algorithm>
 
-enum DIFF_LEVEL{NA=0, EASY=1, MED=2, HARD=3, SCORE=4};
-enum SIGN{PLUS=0, MINUS=1, MULT=2};
+using namespace std;
+extern "C" void mbed_reset();
 
-struct Gen_Question{
+enum DIFF_LEVEL
+{
+    NA = 0,
+    EASY = 1,
+    MED = 2,
+    HARD = 3,
+    SCORE = 4
+};
+
+/*
+------------------STRUCTS
+*/
+
+//Define a question
+struct Gen_Question
+{
     int num1;
     int num2;
     int sign;
@@ -21,7 +36,9 @@
     int ans[4];
 };
 
-struct Game_Difficulty{
+//Define difficulty
+struct Game_Difficulty
+{
     bool is_selected;
     enum DIFF_LEVEL level;
     int ans_time;
@@ -30,31 +47,29 @@
     int score_mult;
 };
 
-struct Game_Settings{
+//Define game settings
+struct Game_Settings
+{
     Game_Difficulty new_diff;
     int score;
-    int live_left; 
+    int live_left;
     int q_on;
     bool is_timeout;
     bool is_lose;
 };
 
-
-Game_Settings new_game = {.q_on=1, .live_left = 3, .new_diff.is_selected=false, .is_timeout=true, .is_lose =false};
-
-
-void print_high_score();
-int* read_high_score();
+Game_Settings new_game = {.q_on = 1, .live_left = 3, .new_diff.is_selected = false, .is_timeout = true, .is_lose = false};
 
 /*
 ------------------CONSTS
 */
-//const int EASY_TIME =20;
-//const int MED_TIME =15;
-//const int HARD_TIME =10;
+const int EASY_TIME = 20;
+const int MED_TIME = 15;
+const int HARD_TIME = 10;
 
-volatile bool homescreen = true;
-volatile bool boot_vid = true;
+const int EASY_NUM_Q = 7;
+const int MED_NUM_Q = 10;
+const int HARD_NUM_Q = 15;
 
 /*
 ------------------I/O VARS
@@ -63,7 +78,7 @@
 RawSerial bluemod(p28, p27);
 Serial pc(USBTX, USBRX);
 uLCD_4DGL uLCD(p9, p10, p11);
-DigitalIn pb(p12);
+InterruptIn pb(p12);
 
 /*
 ------------------LED VARS
@@ -77,23 +92,59 @@
 ------------------AUDIO VARS
 */
 
-FILE *wave_file;
 AnalogOut DACount(p18);
 wave_player waver(&DACount);
 
 /*
 ------------------GENERAL VARS
 */
+volatile bool homescreen = true;
 volatile char bnum = '0';
 
-
+/*
+------------------THREAD VARS
+*/
 Mutex lcd_mutex;
 Mutex blue_mutex;
+Mutex sd_mutex;
 Thread thread1, thread2, thread3;
 
-void main_screen()
+/*
+------------------PROTOTYPES
+*/
+
+void wav_thread();
+void boot_video();
+void print_main_screen();
+void print_high_score();
+int *read_high_score();
+bool count_distinct(int arr[], int n);
+void gen_ans(Gen_Question *gen_new_q);
+void game_questions(Gen_Question *gen_new_q);
+void print_game_over();
+void print_win_game();
+void print_score_game();
+void life_count_check();
+void check_correct_ans(Gen_Question check_new_q);
+void reset_program();
+void reset_scores();
+void check_new_highscore();
+void init();
+void print_high_score();
+int *read_high_score();
+void write_high_score(int *score_arr);
+void bluetooth_thread();
+bool get_bluetooth_button();
+void get_button();
+void rgb_led_difficulty();
+
+
+
+//PRINT THE INTRO SCREEN
+
+void print_main_screen()
 {
-    //pc.printf("MAIN_SCREEN\r\n");
+    //pc.printf("print_main_screen\r\n");
     uLCD.cls();
     uLCD.text_height(1);
     uLCD.text_width(1);
@@ -120,37 +171,109 @@
     homescreen = false;
 }
 
-bool count_distinct(int arr[], int n)
+//PRINT THE WIN GAME SCREEN
+
+void print_win_game()
+{
+    uLCD.cls();
+    uLCD.locate(2, 7);
+    uLCD.text_height(2);
+    uLCD.text_width(2);
+    uLCD.color(GREEN);
+    uLCD.printf("YOU WIN");
+    uLCD.rectangle(0, 0, 127, 127, 0xA89C94);
+}
+
+//PRINT THE GAME OVER SCREEN
+
+void print_game_over()
 {
-    int res = 1;
-    // Pick all elements one by one
-    for (int i = 1; i < n; i++)
+    uLCD.cls();
+    uLCD.locate(0, 7);
+    uLCD.text_height(2);
+    uLCD.text_width(2);
+    uLCD.color(0xFC776A);
+    uLCD.printf("GAME OVER");
+    uLCD.rectangle(0, 0, 127, 127, 0xA89C94);
+}
+
+//PRINT THE CURRENT GAME SCORE
+
+void print_score_game()
+{
+    uLCD.cls();
+    uLCD.locate(4, 3);
+    uLCD.text_height(2);
+    uLCD.text_width(2);
+    uLCD.color(GREEN);
+    uLCD.printf("SCORE");
+    uLCD.rectangle(0, 0, 127, 127, 0xA89C94);
+    uLCD.text_height(1);
+    uLCD.text_width(1);
+    uLCD.locate(7, 7);
+    uLCD.printf("%i", new_game.score);
+}
+
+/*
+Show difficulty selected with RGB led
+Set difficulty parameters
+Or go to high score screen
+
+Get based on value from bluetooth button
+*/
+void rgb_led_difficulty()
+{
+    //pc.printf("%i\r\n",bnum - 48);
+    new_game.new_diff.level = static_cast<DIFF_LEVEL>(bnum - 48);
+    //pc.printf("%i\r\n",new_game.new_diff.level);
+    if (new_game.new_diff.level == EASY)
     {
-        int j = 0;
-        for (j = 0; j < i; j++)
-            if (arr[i] == arr[j])
-                break;
-    // If not printed earlier, then print it
-        if (i == j)
-            res++;
+        myRGBled.write(0.0, 1.0, 0.0); //green
+        new_game.new_diff.is_selected = true;
+        new_game.new_diff.ans_time = EASY_TIME;
+        new_game.new_diff.max_num = 10;
+        new_game.new_diff.num_of_q = EASY_NUM_Q; // 7
+        new_game.score = 50;
+        new_game.new_diff.score_mult = 10;
     }
-    if (res == 4)
+    else if (new_game.new_diff.level == MED)
     {
-        return false;
+        myRGBled.write(1.0, 0.2, 0.0); //yellow = red + some green
+        new_game.new_diff.is_selected = true;
+        new_game.new_diff.ans_time = MED_TIME;
+        new_game.new_diff.max_num = 15;
+        new_game.new_diff.num_of_q = MED_NUM_Q;
+        new_game.score = 200;
+        new_game.new_diff.score_mult = 50;
     }
-    else
+    else if (new_game.new_diff.level == HARD)
     {
-        return true;
+        myRGBled.write(1.0, 0.0, 0.0); //red
+        new_game.new_diff.is_selected = true;
+        new_game.new_diff.ans_time = HARD_TIME;
+        new_game.new_diff.max_num = 10;
+        new_game.new_diff.num_of_q = HARD_NUM_Q;
+        new_game.score = 300;
+        new_game.new_diff.score_mult = 100;
+    }
+    else if (new_game.new_diff.level == SCORE)
+    {
+        myRGBled.write(0.5, 0.5, 0.5);
+        new_game.new_diff.is_selected = true;
     }
 }
-
+/*
+Random generate quesitons with +,-,*
+Use difficulty paramter max_num defining the upper random range
+Generate incorrect questions
+*/
 void gen_ans(Gen_Question *gen_new_q)
 {
     //rand()%(max-min + 1) + min;
     gen_new_q->num1 = rand() % (new_game.new_diff.max_num + 1 - 0) + 0;
     gen_new_q->num2 = rand() % (new_game.new_diff.max_num + 1 - 1) + 1;
     gen_new_q->sign = rand() % (3 + 1 - 1) + 1;
-    
+
     switch (gen_new_q->sign)
     {
     case 1:
@@ -181,6 +304,36 @@
     }
 }
 
+/*
+Check if all the answers generated are distinct
+*/
+bool count_distinct(int arr[], int n)
+{
+    int res = 1;
+    // Pick all elements one by one
+    for (int i = 1; i < n; i++)
+    {
+        int j = 0;
+        for (j = 0; j < i; j++)
+            if (arr[i] == arr[j])
+                break;
+        // If not printed earlier, then print it
+        if (i == j)
+            res++;
+    }
+    if (res == 4)
+    {
+        return false;
+    }
+    else
+    {
+        return true;
+    }
+}
+
+/*
+Handles generating a question, checking distinctness and printing to the screen
+*/
 void game_questions(Gen_Question *gen_new_q)
 {
     gen_ans(gen_new_q);
@@ -201,7 +354,7 @@
     uLCD.text_height(2);
     uLCD.text_width(2);
     uLCD.color(0xFC766A);
-    uLCD.printf("Q%i",new_game.q_on);
+    uLCD.printf("Q%i", new_game.q_on);
     uLCD.text_height(1);
     uLCD.text_width(1);
 
@@ -256,61 +409,12 @@
     uLCD.line(0, 115, 127, 115, 0xA89C94);
 }
 
-void game_over()
-{
-    uLCD.cls();
-    uLCD.locate(0, 7);
-    uLCD.text_height(2);
-    uLCD.text_width(2);
-    uLCD.color(0xFC776A);
-    uLCD.printf("GAME OVER");
-    uLCD.rectangle(0, 0, 127, 127, 0xA89C94);
-}
-
-void win_game()
-{
-    uLCD.cls();
-    uLCD.locate(2, 7);
-    uLCD.text_height(2);
-    uLCD.text_width(2);
-    uLCD.color(GREEN);
-    uLCD.printf("YOU WIN");
-    uLCD.rectangle(0, 0, 127, 127, 0xA89C94);
-
-}
-
-void score_game()
-{
-    uLCD.cls();
-    uLCD.locate(1, 3);
-    uLCD.text_height(2);
-    uLCD.text_width(2);
-    uLCD.color(GREEN);
-    uLCD.printf("SCORE");
-    uLCD.rectangle(0, 0, 127, 127, 0xA89C94);
-    uLCD.text_height(1);
-    uLCD.text_width(1);
-    uLCD.locate(7, 7);
-    uLCD.printf("%i",new_game.score);
-}
-
-void life_count_check()
-{
-    life[0] = 0;
-    life[1] = 0;
-    life[2] = 0;
-
-    for (int i = 0; i < new_game.live_left; i++)
-    {
-        life[i] = 1;
-    }
-    if (new_game.live_left == 0)
-    {
-        new_game.is_lose = true;
-
-    }
-}
-
+/*
+Check if question was answered correctly
+Wait on bluetooth ans or timeout
+Prints correct, incorrect, or timeout as necessary
+Removes lives as necessary
+*/
 void check_correct_ans(Gen_Question check_new_q)
 {
     if (new_game.is_timeout)
@@ -358,12 +462,54 @@
     }
 }
 
+/*
+Set LEDs for lives correctly
+If No more lives then print lose screen
+*/
+void life_count_check()
+{
+    life[0] = 0;
+    life[1] = 0;
+    life[2] = 0;
 
+    for (int i = 0; i < new_game.live_left; i++)
+    {
+        life[i] = 1;
+    }
+    if (new_game.live_left == 0)
+    {
+        new_game.is_lose = true;
+    }
+}
+
+/*
+Used initially to call bluetooth button click gathering
+Only used on the main screen
+*/
+void bluetooth_thread()
+{
+    while (true)
+    {
+        if (bluemod.readable())
+        {
+            bool n_timeout = get_bluetooth_button();
+        }
+        else
+        {
+            Thread::yield();
+        }
+        Thread::wait(100);
+    }
+}
+
+/*
+Gets button clicks from bluetooth
+*/
 bool get_bluetooth_button()
 {
     //pc.printf("BLUETOOTH\r\n");
     bnum = '0';
-    //blue_mutex.lock();
+    blue_mutex.lock();
     if (bluemod.getc() == '!')
     {
         if (bluemod.getc() == 'B')
@@ -383,10 +529,15 @@
             }
         }
     }
-    //blue_mutex.unlock();
+    blue_mutex.unlock();
     return true;
 }
 
+/*
+Prints timer during main game
+Checks if the bluetooth gives a button click
+If button is clicked stops timer then checks answer
+*/
 void get_button()
 {
     int timer = new_game.new_diff.ans_time;
@@ -399,7 +550,8 @@
         if (bluemod.readable())
         {
             new_game.is_timeout = get_bluetooth_button();
-            if(new_game.is_timeout == false){
+            if (new_game.is_timeout == false)
+            {
                 break;
             }
         }
@@ -408,143 +560,131 @@
         uLCD.color(BLACK);
         uLCD.printf("%i", timer);
         timer = timer - 1;
-
-    }
-}
-
-void bluetooth_thread()
-{
-    while (true)
-    {
-        if (bluemod.readable())
-        {
-            bool n_timeout = get_bluetooth_button();
-        }
-        else
-        {
-            Thread::yield();
-        }
-        Thread::wait(100);
     }
 }
 
-void rgb_led_difficulty()
-{
-    //pc.printf("%i\r\n",bnum - 48);
-    new_game.new_diff.level = static_cast<DIFF_LEVEL>(bnum - 48);
-    //pc.printf("%i\r\n",new_game.new_diff.level);
-    if (new_game.new_diff.level == EASY)
-    {
-        myRGBled.write(0.0, 1.0, 0.0); //green
-        new_game.new_diff.is_selected = true;
-        new_game.new_diff.ans_time = 20;
-        new_game.new_diff.max_num = 10;
-        new_game.new_diff.num_of_q = 7; // 7
-        new_game.score = 50;
-        new_game.new_diff.score_mult = 10;
-    }
-    else if (new_game.new_diff.level == MED)
-    {
-        myRGBled.write(1.0, 0.2, 0.0); //yellow = red + some green
-        new_game.new_diff.is_selected = true;
-        new_game.new_diff.ans_time = 15;
-        new_game.new_diff.max_num = 15;
-        new_game.new_diff.num_of_q = 10;
-        new_game.score = 200;
-        new_game.new_diff.score_mult = 50;
-    }
-    else if (new_game.new_diff.level == HARD)
-    {
-        myRGBled.write(1.0, 0.0, 0.0); //red
-        new_game.new_diff.is_selected = true;
-        new_game.new_diff.ans_time = 10;
-        new_game.new_diff.max_num = 10;
-        new_game.new_diff.num_of_q = 15;
-        new_game.score = 300;
-        new_game.new_diff.score_mult = 100;
-    }
-    else if (new_game.new_diff.level == SCORE)
-    {
-        myRGBled.write(0.5, 0.5, 0.5);
-        new_game.new_diff.is_selected = true;
-        print_high_score();
-    }
-}
-
+/*
+Plays background music
+*/
 void wav_thread()
 {
     while (true)
     {
-        //pc.printf("AUDIO\r\n");
+        FILE *wave_file;
         wave_file = fopen("/sd/audio/intro.wav", "r");
         waver.play(wave_file);
         fclose(wave_file);
     }
 }
 
-void boot_video_thread()
+/*
+Plays bootup video
+*/
+void boot_video()
 {
-    while (true)
-    {
-        //pc.printf("BootVID\r\n");
-        //PLAY VIDEO BOOT
-        if (boot_vid)
-        {
-            //lcd_mutex.lock();
-            uLCD.media_init();
-            uLCD.set_sector_address(0x0, 0x0);
-            uLCD.display_video(0, 0);
-            boot_vid = false;
-            //lcd_mutex.unlock();
-        }
-        else
-        {
-            Thread::yield();
-        }
-    }
+    uLCD.media_init();
+    uLCD.set_sector_address(0x0, 0x0);
+    uLCD.display_video(0, 0);
 }
 
-void write_high_score(int* score_arr){
+/*
+write high scores to file
+*/
+void write_high_score(int *score_arr)
+{
     std::ofstream score_file;
     score_file.open("/sd/score/score.txt");
     if (score_file.is_open())
     {
-            //score_file << "300\n200\n100\n";
-            score_file << score_arr[0] << "\n" << score_arr[1] << "\n" << score_arr[2] << "\n";
-            score_file.close();
+        //score_file << "300\n200\n100\n";
+        score_file << score_arr[0] << "\n"
+                   << score_arr[1] << "\n"
+                   << score_arr[2] << "\n";
+        score_file.close();
     }
 }
 
-
-int* read_high_score()
+/*
+read high scores from file
+*/
+int *read_high_score()
 {
-    int* score_val = new int[3];
-    //printf("read_high_score\n\r");
+    int *score_val = new int[3];
+    printf("read_high_score\n\r");
     std::ifstream infile("/sd/score/score.txt");
-    wait(0.2);
-    if (infile.is_open())
+    while(!infile){
+        std::ifstream infile("/sd/score/score.txt");
+        wait(1);
+    }
+    if (infile)
     {
+        printf("file open\n\r");
         std::string line;
         int i = 0;
-        while (std::getline(infile, line)) {
+        while (std::getline(infile, line))
+        {
             // using printf() in all tests for consistency
             //printf("%s", line.c_str());
             score_val[i] = atoi(line.c_str());
             i++;
         }
-        infile.close();
     }
+    infile.close();
+    //.printf("%i \n\r", strerror(errno));
     pc.printf("%i \n\r", score_val[0]);
     pc.printf("%i \n\r", score_val[1]);
     pc.printf("%i \n\r", score_val[2]);
-    
+
     return score_val;
 }
 
-void print_high_score(){
-    
-    int* score_arr= read_high_score();
-        
+/*
+check if there is a new highscore
+if so shift high scores as necessary
+*/
+void check_new_highscore()
+{
+    int *new_score_arr = read_high_score();
+    for (int i = 0; i < 3; i++)
+    {
+        if (new_score_arr[i] < new_game.score)
+        {
+            int j = 1;
+            while (i <= j)
+            {
+                new_score_arr[j + 1] = new_score_arr[j];
+                j--;
+            }
+            new_score_arr[i] = new_game.score;
+            //pc.printf("high score found");
+            write_high_score(new_score_arr);
+            break;
+        }
+    }
+    delete[] new_score_arr;
+}
+
+/*
+Rest high scores to 0
+*/
+void reset_scores()
+{
+    mkdir("/sd/score", 0777);
+    std::ofstream score_file;
+    score_file.open("/sd/score/score.txt");
+    if (score_file.is_open())
+    {
+        score_file << "30\n20\n10\n";
+        score_file.close();
+    }
+}
+
+//PRINT THE STORES HIGH SCORES
+void print_high_score()
+{
+    //pc.printf("GET SCORE");
+    int *score_arr = read_high_score();
+    pc.printf("PRINTING SCORES");
     uLCD.cls();
     uLCD.text_height(1);
     uLCD.text_width(1);
@@ -556,78 +696,63 @@
     uLCD.printf("1) %i", score_arr[0]);
     uLCD.locate(3, 8);
     uLCD.color(0x669DB2);
-    uLCD.printf("2) %i",  score_arr[1]);
+    uLCD.printf("2) %i", score_arr[1]);
     uLCD.locate(3, 10);
     uLCD.color(0xFC776A);
-    uLCD.printf("3) %i",  score_arr[2]);
+    uLCD.printf("3) %i", score_arr[2]);
     uLCD.rectangle(0, 0, 127, 127, 0xA89C94);
-    delete[] score_arr;    
+    delete[] score_arr;
 }
 
-void check_new_highscore(){
-    int* new_score_arr = read_high_score();
-    for (int i = 0; i < 3; i++)
-        {
-            if (new_score_arr[i]< new_game.score){
-                int j = 1;
-                while(i<=j){
-                    new_score_arr[j+1] = new_score_arr[j];
-                    j--;
-                }
-                new_score_arr[i] = new_game.score;
-                pc.printf("high score found");
-                write_high_score(new_score_arr);
-                break;
-            }
-        }
-    delete[] new_score_arr;
-}
 
-void reset_scores(){
-    mkdir("/sd/score", 0777);
-    std::ofstream score_file;
-    score_file.open("/sd/score/score.txt");
-    if (score_file.is_open())
-    {
-            score_file << "0\n0\n0\n";
-            score_file.close();
-    }
-}
-
+/*
+Initialize mbed paramters
+set lives
+start boot video
+*/
 void init()
 {
+
 //    while(1){
+//        print_high_score();
 //        reset_scores();
-//        wait(2);
+//        wait(5);   
 //    }
+    pb.mode(PullUp);
+    pb.rise(&reset_program);
     uLCD.baudrate(3000000);
     srand(time(NULL));
     life[0] = 1;
     life[1] = 1;
     life[2] = 1;
-    //thread1.start(boot_video_thread);
-    boot_vid = false;
+    boot_video();
 }
-
+/*
+reset mbed
+*/
+void reset_program()
+{
+    mbed_reset();
+}
 
 int main()
 {
+    //START PLAYING MUSIC
+    thread2.start(wav_thread);
     init();
-//    pc.printf("MAIN_INIT\r\n\n");
-    thread2.start(wav_thread);
+    //pc.printf("MAIN_INIT\r\n\n");
     while (true)
     {
         //pc.printf("MAIN_LOOP\r\n");
-        //ONCE VIDEO STOPS PLAYING
-        if (boot_vid == false)
-        {
-            thread1.terminate();
+        
             //IF HOMESCREEN PRINTED ONCE DONT PRINT AGAIN
             if (homescreen)
             {
-                main_screen();
+                print_main_screen();
             }
-            //pc.printf("MAIN_PRINT\r\n");
+            //WAIT UNTIL DIFFICULTY IS SELECTED
+            //IF SELECTED TURN ON LED COLOR
+            //TURN OFF BLUETOOTH THREAD DONT WANT
             if (new_game.new_diff.is_selected == false)
             {
                 thread3.start(bluetooth_thread);
@@ -636,12 +761,23 @@
             else
             {
                 thread3.terminate();
+                if(new_game.new_diff.level == SCORE){
+                    thread2.terminate();
+                    DACount = 0.0;
+                    print_high_score();
+
+                }
                 break;
             }
-        }
+
         Thread::wait(100);
     }
-    if(new_game.new_diff.level != SCORE){
+    //WHEN NOT SELECTED HIGH SCORE LEVL
+    if (new_game.new_diff.level != SCORE)
+    {
+        //KEEP PRINTING QUESTIONS UNTIL DEFINED DIFFICULTY
+        //CHECK ANSWERS, LIVES
+        //PRINT LOSE OR WIN GAME SCREENS
         while (new_game.q_on <= new_game.new_diff.num_of_q)
         {
             thread3.terminate();
@@ -652,17 +788,23 @@
             new_game.q_on++;
             wait(2.2);
             life_count_check();
-            if(new_game.is_lose == true){
-                game_over();
+            if (new_game.is_lose == true)
+            {
+                print_game_over();
                 break;
             }
         }
-        if(new_game.is_lose == false){
-            win_game();
+        if (new_game.is_lose == false)
+        {
+            print_win_game();
         }
+        //CALCULATE SCORE OF THE GAME PRINT
+        //PRINT HIGH SCORES
         wait(2.5);
         new_game.score = new_game.score + new_game.live_left * 100;
-        score_game();
+        print_score_game();
+        thread2.terminate();
+        DACount = 0.0;
         wait(2);
         check_new_highscore();
         wait(0.5);