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

main.cpp

Committer:
rushib1
Date:
2020-04-26
Revision:
2:acd4656312d8
Parent:
0:5bb514318c64
Child:
3:6e41a5ce16c2

File content as of revision 2:acd4656312d8:

#include "mbed.h"
#include "uLCD_4DGL.h"
#include "rgb.h"
#include "SDFileSystem.h"
#include "wave_player.h"
#include "rtos.h"

#include <string>
#include <iostream>
#include <fstream>
#include <algorithm>

using namespace std;

/*
------------------CONSTS
*/

volatile bool homescreen = true;
volatile bool diff_selected = false;
volatile bool boot_vid = true;
bool timeout = true;
bool game_is_over = false;

/*
------------------I/O VARS
*/
SDFileSystem sd(p5, p6, p7, p8, "sd");
RawSerial bluemod(p28, p27);
Serial pc(USBTX, USBRX);
uLCD_4DGL uLCD(p9, p10, p11);
DigitalIn pb(p12);

/*
------------------LED VARS
*/

DigitalOut life[] = {(p16), (p19), (p20)};
RGBLed myRGBled(p21, p24, p23);
DigitalOut onboard_led(LED1);

/*
------------------AUDIO VARS
*/

FILE *wave_file;
AnalogOut DACount(p18);
wave_player waver(&DACount);

/*
------------------GENERAL VARS
*/
int difficulty = 0;
string scores;
int score_val[3];
volatile char bnum;
int ans[4];
int corr_ans;
char sign;
int live_left = 3;

Mutex lcd_mutex;
Mutex blue_mutex;
Thread thread1, thread2, thread3;

void main_screen()
{

    //while(true){
    //        if(homescreen){
    pc.printf("MAIN_SCREEN\r\n");
    lcd_mutex.lock();
    uLCD.cls();
    uLCD.text_height(1.9);
    uLCD.text_width(1.9);
    uLCD.color(WHITE);
    uLCD.locate(6, 1);
    uLCD.printf("MATH FUN");
    //MAKE MATH FUN BLINK
    uLCD.locate(1, 4);
    uLCD.text_height(1.3);
    uLCD.printf("Difficulty");
    uLCD.text_height(1.3);
    uLCD.text_width(1.9);
    uLCD.locate(3, 6);
    uLCD.color(GREEN);
    uLCD.printf("1) Easy");
    uLCD.locate(3, 8);
    uLCD.color(0xFFFF00);
    uLCD.printf("2) Not as Easy");
    uLCD.locate(3, 10);
    uLCD.color(RED);
    uLCD.printf("3) Very Uneasy");
    uLCD.color(BLUE);
    uLCD.locate(1, 13);
    uLCD.printf("4) High Scores");
    lcd_mutex.unlock();
    //pc.printf("thread 1\r\n");
    homescreen = false;
    //  Thread::wait(100);
    // }
    // else{
    //     Thread::yield();
    // }
    //}
}

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;
    }
}

void gen_ans(int &num1, int &num2, int sign_val)
{

    switch (sign_val)
    {
    case 1:
        sign = '*';
        ans[0] = num1 * num2;
        ans[1] = (num1 + (rand() % (10 + 1 - 1) + 1)) * num2;
        ans[2] = (num1 * num2) + (rand() % (20 + 1 - 1) + 1);
        ans[3] = (num1 * num2) + (rand() % (20 + 1 - 1) + 1);
        break;
    case 2:
        sign = '+';
        ans[0] = num1 + num2;
        ans[1] = (num1 + (rand() % (10 + 1 - 1) + 1)) + num2;
        ans[2] = (num1 + num2) - (rand() % ((num1 + num2) + 1 - 1) + 1);
        ans[3] = (num1 * num2) + (rand() % (10 + 1 - 1) + 1);
        break;
    case 3:
        sign = '-';
        //rand()%(max-min + 1) + min;
        while (num1 == num2)
        {
            num1 = (rand() % ((num1 + 2) - 1 + 1) + 1);
        }
        ans[0] = num1 - num2;
        ans[1] = (num1 - num2) * -1 + (rand() % (10 + 1 - 1) + 1);
        ans[2] = num1 + num2 - (rand() % (10 + 1 - 1) + 1);
        ans[3] = num1 * num2 - (rand() % (20 + 1 - 1) + 1);
        break;
    case 4:
        sign = '/';
        ans[0] = num1 - num2;
        break;
    }
}

void game_questions()
{
    int gen1 = rand() % (10 + 1 - 0) + 0;
    int gen2 = rand() % (10 + 1 - 1) + 1;
    int gen_sign = rand() % (3 + 1 - 1) + 1;
    gen_ans(gen1, gen2, gen_sign);
    bool reroll = count_distinct(ans, 4);
    while (reroll)
    {
        gen_ans(gen1, gen2, gen_sign);
        reroll = count_distinct(ans, 4);
        //pc.printf("reroll\r\n");
    }

    corr_ans = ans[0];
    random_shuffle(&ans[0], &ans[3]);

    uLCD.cls();
    uLCD.locate(2, 1);
    uLCD.text_height(2);
    uLCD.text_width(2);
    uLCD.color(0xFC766A);
    uLCD.printf("Q1");
    uLCD.text_height(1);
    uLCD.text_width(1);

    uLCD.locate(9, 1);
    uLCD.printf("TIME:");
    uLCD.line(55, 0, 55, 27, 0xA89C94);

    uLCD.rectangle(0, 0, 127, 127, 0xA89C94);
    uLCD.line(0, 27, 127, 27, 0xA89C94);
    uLCD.line(0, 50, 127, 50, 0xA89C94);

    uLCD.color(0x669DB2);
    uLCD.locate(2, 4);
    uLCD.text_height(2);
    uLCD.text_width(2);
    uLCD.printf("%i%c%i=", gen1, sign, gen2);
    uLCD.text_height(1);
    uLCD.text_width(1);

    uLCD.color(0xFC766A);
    uLCD.locate(2, 7);
    uLCD.printf("1)");

    uLCD.color(0x669DB2);
    uLCD.locate(8, 7);
    uLCD.printf("%i", ans[0]);

    uLCD.color(0xFC766A);
    uLCD.locate(2, 9);
    uLCD.printf("2)");

    uLCD.color(0x669DB2);
    uLCD.locate(8, 9);
    uLCD.printf("%i", ans[1]);

    uLCD.color(0xFC766A);
    uLCD.locate(2, 11);
    uLCD.printf("3)");

    uLCD.color(0x669DB2);
    uLCD.locate(8, 11);
    uLCD.printf("%i", ans[2]);

    uLCD.color(0xFC766A);
    uLCD.locate(2, 13);
    uLCD.printf("4)");

    uLCD.color(0x669DB2);
    uLCD.locate(8, 13);
    uLCD.printf("%i", ans[3]);

    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");
    game_is_over = true;
    wait(2);
}

void life_count_check()
{
    life[0] = 0;
    life[1] = 0;
    life[2] = 0;

    for (int i = 0; i < live_left; i++)
    {
        life[i] = 1;
    }
    if (live_left == 0)
    {
        game_over();
    }
}

void check_correct_ans()
{
    if (timeout)
    {
        //pc.printf("TIMEOUT\r\n");
        uLCD.cls();
        uLCD.locate(5, 7);
        uLCD.text_height(2);
        uLCD.text_width(2);
        uLCD.color(0xF0F6F7);
        uLCD.printf("TIME");
        live_left--;
        //wait(2);
    }
    else
    {
        //pc.printf("%i\r\n", corr_ans);
        //pc.printf("%i\r\n", ans[(bnum-'0' -1)]);

        if (corr_ans == ans[(bnum - '0') - 1])
        {

            uLCD.cls();
            uLCD.locate(2, 7);
            uLCD.text_height(2);
            uLCD.text_width(2);
            uLCD.color(GREEN);
            uLCD.printf("CORRECT");
            //wait(2);
            //pc.printf("CORRECT\r\n");
        }
        else
        {
            //pc.printf("INCORRECT\r\n");
            uLCD.cls();
            uLCD.locate(0, 7);
            uLCD.text_height(2);
            uLCD.text_width(2);
            uLCD.color(RED);
            uLCD.printf("INCORRECT");
            live_left--;
            //wait(2);
        }
    }
}


bool get_bluetooth_button()
{
    pc.printf("BLUETOOTH\r\n");
    blue_mutex.lock();
    if (bluemod.getc() == '!')
    {
        if (bluemod.getc() == 'B')
        {
            //button number
            bnum = bluemod.getc();
            //button data
            char bhit = bluemod.getc();
            if (bluemod.getc() == char(~('!' + 'B' + bnum + bhit)))
            {
                if (bhit == '1')
                {
                    pc.printf("%c\r\n", bnum);
                    blue_mutex.unlock();
                    return false;
                }
            }
        }
    }
    blue_mutex.unlock();
    return true;
}

void get_button()
{
    int timer = 10;
    timeout = true;
    while (timer != 0)
    {
        uLCD.locate(15, 1);
        uLCD.color(0xF0F6F7);
        uLCD.printf("%i", timer);
        if (bluemod.readable())
        {
            timeout = get_bluetooth_button();
            if(timeout == false){
                break;
            }
        }
        wait(1);
        uLCD.locate(15, 1);
        uLCD.color(BLACK);
        uLCD.printf("%i", timer);
        timer = timer - 1;
        //pc.printf("%i\r\n", x);
    }
}



void bluetooth_thread()
{
    while (true)
    {
        if (bluemod.readable())
        {
            bool n_timeout = get_bluetooth_button();
        }
        else
        {
            Thread::yield();
        }
        Thread::wait(100);
    }
}

void rgb_led_difficulty()
{
    difficulty = bnum - 48;
    //pc.printf("%i\r\n",difficulty);
    if (difficulty == 1)
    {
        myRGBled.write(0.0, 1.0, 0.0); //green
        diff_selected = true;
    }
    else if (difficulty == 2)
    {
        myRGBled.write(1.0, 0.2, 0.0); //yellow = red + some green
        diff_selected = true;
    }
    else if (difficulty == 3)
    {
        myRGBled.write(1.0, 0.0, 0.0); //red
        diff_selected = true;
    }
}

void wav_thread()
{
    while (true)
    {
        pc.printf("AUDIO\r\n");
        wave_file = fopen("/sd/audio/intro.wav", "r");
        waver.play(wave_file);
        fclose(wave_file);
    }
}

void boot_video_thread()
{
    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();
        }
    }
}

void init()
{
    uLCD.baudrate(3000000);
    srand(time(NULL));
    life[0] = 1;
    life[1] = 1;
    life[2] = 1;
    thread1.start(boot_video_thread);
}

int main()
{

    init();
    pc.printf("MAIN_INIT\r\n\n");
    thread2.start(wav_thread);
    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();
            }
            //pc.printf("MAIN_PRINT\r\n");
            //break;
            if (diff_selected == false)
            {
                thread3.start(bluetooth_thread);
                rgb_led_difficulty();
            }
            else
            {
                thread3.terminate();
                break;
            }
        }
        Thread::wait(200);
    }
    while (!game_is_over)
    {
        game_questions();
        get_button();
        check_correct_ans();
        wait(2);
        life_count_check();
    }
}