ECE 4180 Final

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

Revision:
19:d65f9fb1023b
Parent:
11:362e25f659a5
Child:
20:7d56cdcbc9a5
--- a/main.cpp	Thu Dec 05 05:13:16 2019 +0000
+++ b/main.cpp	Fri Dec 06 15:46:16 2019 +0000
@@ -1,28 +1,30 @@
 #include "mbed.h"
 #include "rtos.h"
+#include "stdio.h"
 #include "SDFileSystem.h"
 #include "wave_player.h"
+
 #include "uLCD_4DGL.h"
-
-//setup some color objects in flash using const's
-
 #include "Small_6.h"
 #include "Small_7.h"
 #include "Arial_9.h"
-#include "stdio.h"
 #include "C12832_lcd.h"
 
+#include "globals.h"
+
 #include "bubbles.h"
 #include "stacys_mom.h"
-#include "the_middle.h"
+//#include "the_middle.h"
 #include "fireflies.h"
 #include "sins.h"
 #include "LED.hpp"
 
- 
+#include "Lane.hpp"
+#include "Bubble.hpp"
+
+
 //Setup RGB led using PWM pins and class
 RGBLed myRGBled(p24,p23,p22); //RGB PWM pins
-
 char bred=0;
 char bgreen=0;
 char bblue=0; 
@@ -33,26 +35,34 @@
 volatile bool playing = false;
 uLCD_4DGL uLCD(p28,p27,p30);
 SDFileSystem sd(p5, p6, p7, p8, "sd"); //SD card
+AnalogIn joy_pot(p16);
 DigitalOut myled(LED1);
 DigitalIn pb1(p20);
 DigitalIn pb2(p19);
 AnalogOut DACout(p18);
 wave_player waver(&DACout);
-Thread thread1, thread2, thread3;
+Thread thread1, thread2, thread3, thread4;
+
 Ticker nextsample;
-int songNdx = 0;
+volatile int songNdx = 0;
+unsigned char *playingSong = NULL;
 
 // mutex to make the lcd lib thread safe
 Mutex lcd_mutex;
 int songnum = 1;
-AnalogIn joy_pot(p16);
+
+unsigned short **currentBubbles = NULL;
+int bubbleNdx = 0;
+int bubblesDrawn = 0;
+int bubblesMissed = 0;
+
+
 
 // Thread 1
 // print homescreen to LCD
-//new homescreen that doesn't have the flashing 
 void homescreen_thread()
 {
-    while(true) {       // thread loop
+    while (true) {       // thread loop
         lcd_mutex.lock();
         if (homescreen){
             uLCD.cls();
@@ -70,141 +80,265 @@
             uLCD.locate(3,5);
             uLCD.printf("Fireflies");
             uLCD.locate(3,7);
-            uLCD.printf("The Middle");
+            uLCD.printf("Stacy's Mom");
             uLCD.locate(3,9);
-            uLCD.printf("Stacy's Mom");
-            uLCD.locate(3,11);
             uLCD.printf("I Write Sins \n \t  Not Tragedies");
-            uLCD.filled_circle(6, 43, 4, GREEN); //new selection with circle instead of rectangle
-            homescreen = false;}
-        if (songchange){
-            for (int i = 0; i < 4; i++){
-            uLCD.filled_circle(6, i*15+43, 4,BLACK);
+            uLCD.filled_circle(6, 43, 4, WHITE); //new selection with circle instead of rectangle
+            homescreen = false;
+        }
+        if (songchange) {
+            for (int i = 0; i < 3; i++){
+                uLCD.filled_circle(6, i*15+43, 4,BLACK);
             }
-            uLCD.filled_circle(6, (songnum-1)*15+43, 4,GREEN);
+            uLCD.filled_circle(6, (songnum-1)*15+43, 4,WHITE);
             songchange = false;
-            }
-            lcd_mutex.unlock();
-            Thread::wait(200);
+        }
+
+        lcd_mutex.unlock();
+        Thread::wait(200);
     }
 }
 
 // Thread 2
 // joystick control for song selection during homescreen
-void joystick_thread()
-{
-   while(1){
+void joystick_thread() {
+   while (true) {
+        if (!playing) { // we dont want to be able to change the song if we're playing
             if ((joy_pot <= (1.4/3.3)) && songnum>1) {
-                songnum--;
-                songchange = true;
-                }
-            else if ((joy_pot >= (1.8/3.3)) && songnum<4){
+            songnum--;
+            songchange = true;
+            } else if ((joy_pot >= (1.8/3.3)) && songnum<3){
                 songnum++;
                 songchange = true;
-                }
-        Thread::wait(250);
+            }
+            Thread::wait(250);
+        }
+        
     }
 }
 
 // Thread 3
-//pb1 is to select song
-//pb2 is to return to homescreen
+// reads pushbuttons to control menu
 void pbcontrol_thread()
 {
-    pb1.mode(PullUp);
-    pb2.mode(PullUp);
+    // The pb variables will be zero when the pushbutton is pressed
+    pb1.mode(PullUp); //pb1 is to select song
+    pb2.mode(PullUp); //pb2 is to return to homescreen
     while(true) {       // thread loop
-        if (!pb2)
-            {
+        if (!pb2) {
             homescreen = true;
             songselect = false;
-            }
-        if (!pb1)
-            {
+            playing = false;
+        }
+        if (!pb1) {
             songselect = true;
-            }
-        Thread::wait(100);   // value of pot1 / 100
+        }
+        Thread::wait(100); 
     }
 }
 
 // Thread 4
+// control LED effects
+void LED_thread() {
+    while (true) {
+        if (!playing) { //spin LED colors at start menu
+            myRGBled = red;
+            Thread::wait(200);
+            myRGBled = yellow;
+            Thread::wait(200);
+            myRGBled = orange;
+            Thread::wait(200);
+            myRGBled = blue;
+            Thread::wait(200);
+            myRGBled = green;
+            Thread::wait(200);
+        } else if (playing) {
+            
+            if (bubblesMissed <= 3) {
+                myRGBled = green;
+            } else if (bubblesMissed <= 5) {
+                myRGBled = yellow;
+            } else {
+                myRGBled = red;
+            }
+            
+            Thread::wait(300);
+            
+        }
+    }
+}
+
+// Thread 5
 // this thread plays music using the ticker class
 void playsound() {
     if (playing) {
-        //DACout = song[songNdx++];
-        //if (i>**songlength**) i 
+        DACout.write(playingSong[songNdx++] / 255.0);
+        if (songNdx>120000) {
+            playing = false;
+            songNdx = 0;
+        } 
     } else {
-        DACout = 0;
+        DACout.write(0.0);
         songNdx = 0;
     }
 }
 
+void pickSong() {
+    switch (songnum) {
+        case 1:
+        {
+            playingSong = (unsigned char *) fireflies;
+            playing = true;
+            break;
+        }
+        
+        case 2:
+        {
+            playingSong = (unsigned char *) stacys_mom;
+            playing = true;
+            break;
+        }
+        case 3:
+        {
+            playingSong = (unsigned char *) sins;
+            playing = true;
+            break;
+        }
+        default:
+            break;
+    }
+}
+
+
+
+void showScore () {
+    uLCD.color(0x00FF00);        // Change text color and set up menu
+    uLCD.text_bold(ON);
+    uLCD.locate(1,1);
+    uLCD.text_width(2); //4X size text
+    uLCD.text_height(2);
+    uLCD.printf("Thanks for playing Tap Tap Revolution!");
+//    winSound();
+    wait(1.5);
+    
+    uLCD.text_width(1); //4X size text
+    uLCD.text_height(1);
+    uLCD.text_bold(OFF);
+    uLCD.color(0xFFFFFF);
+    uLCD.locate(2,8);
+    uLCD.printf("Your Score:");
+    uLCD.color(0x00FF00);
+    uLCD.locate(2,10);
+    
+     float scorePercent = ((bubblesDrawn - bubblesMissed) / bubblesDrawn) * 100;
+    uLCD.printf("%d %", scorePercent);
+    wait(1.2);   
+    uLCD.cls();
+    uLCD.locate(5,0);
+    
+    Thread::wait(2000);
+}
+
+
+void play() {
+    Lane *bubbleLanes[3];
+    // these positions may need to be adjusted as I assume they're positioned incorrectly...
+    bubbleLanes[0] = new Lane(3,3);
+    bubbleLanes[1] = new Lane(3,6);
+    bubbleLanes[2] = new Lane(3,9);
+    
+    while (playing && !bubbleLanes[0]->isEmpty() && !bubbleLanes[1]->isEmpty() && !bubbleLanes[2]->isEmpty())  {
+        
+    }
+    
+    // return to homescreen when
+    homescreen = true;
+}
+
+
+
 int main() {
     
-    uLCD.baudrate(3000000);
+    uLCD.baudrate(3000000); // set baud rate to max
+    
     thread1.start(homescreen_thread);
     thread2.start(joystick_thread);
     thread3.start(pbcontrol_thread);
-//    nextsample.attach(&playsound, 1.0/8000.0);
-    //startup sound
-    myRGBled = blue; //tested to make sure led works, we can use whatever color(s) here
-    FILE *wave_file;
-    wave_file=fopen("/sd/cheer.wav","r");
-    waver.play(wave_file);
-    fclose(wave_file);
-    while(1) 
-    {
-        
-        if (songselect){
-                myled = 0;
-                homescreen = false;
-                lcd_mutex.lock();
-                uLCD.cls();
-                uLCD.printf("You selected song %2d",songnum);
-                lcd_mutex.unlock();
-                //add case statement based on songnum or something
-                //code for playing song from sd
-                switch (songnum)
-                {
-                case 1:
-                {
-                FILE *wave_file;
-                wave_file =fopen("/sd/4180 final project/Fireflies.wav", "r");
-                waver.play(wave_file);
-                fclose(wave_file);
-                break;
+    thread4.start(LED_thread);
+    nextsample.attach(&playsound, 1.0/8000.0);
+    
+    Lane *bubbleLanes[3];
+    // these positions may need to be adjusted as I assume they're positioned incorrectly...
+    bubbleLanes[0] = new Lane(15,15);
+    bubbleLanes[1] = new Lane(40,15);
+    bubbleLanes[2] = new Lane(80,15);
+    
+    //startup sound?
+    
+    while(true) {
+        if (songselect) {
+            homescreen = false;
+//            lcd_mutex.lock();
+//            uLCD.cls();
+//            uLCD.printf("You selected song %2d", songnum);
+//            lcd_mutex.unlock();
+            pickSong();
+            
+            // "playing" is updated by playsound() thread
+            while (playing && !bubbleLanes[0]->isEmpty() && !bubbleLanes[1]->isEmpty() && !bubbleLanes[2]->isEmpty())  {
+                // draw unufilled circles at the bottom of the screen where the user should "tap"
+                uLCD.circle(15,110, 30, GREEN);
+                uLCD.circle(40,110, 30, GREEN);
+                uLCD.circle(80,110, 30, GREEN);
+                
+                // add bubbles to lanes
+                if (fireflies_bubbles[bubbleNdx][0] > songNdx) { // check if it's time to load a bubble
+                    bool addedbubbles = false;
+                    if (fireflies_bubbles[bubbleNdx][2] > songNdx) { // check if add bubble at ndx
+                        bubbleLanes[0]->add();
+                        addedbubbles = true;
+                    }
+                
+                    if (fireflies_bubbles[bubbleNdx][3] > songNdx) { // check if add bubble at ndx
+                        bubbleLanes[1]->add();
+                        addedbubbles = true;
+                    }
+                
+                     if (fireflies_bubbles[bubbleNdx][4] > songNdx) { // check if add bubble at ndx
+                        bubbleLanes[2]->add();
+                        addedbubbles = true;
+                     }
+                     
+                     if (addedbubbles) ++songNdx;
                 }
-                case 2:
-                {
-                FILE *wave_file;
-                wave_file =fopen("/sd/4180 final project/The_Middle.wav", "r");
-                waver.play(wave_file);
-                fclose(wave_file);
-                break;
-                }
-                case 3:
-                {
-                FILE *wave_file;
-                wave_file =fopen("/sd/4180 final project/Stacy's_Mom.wav", "r");
-                waver.play(wave_file);
-                fclose(wave_file);
-                break;
-                }
-                case 4:
-                {
-                FILE *wave_file;
-                wave_file =fopen("/sd/4180 final project/Sins_!_Tragedies.wav", "r");
-                waver.play(wave_file);
-                fclose(wave_file);
-                break;
-                }
-                default:
-                break;
+                
+                // draw all bubbles
+                bubbleLanes[0]->draw();
+                bubbleLanes[1]->draw();
+                bubbleLanes[2]->draw();
+                
+                // TODO: check for hits with capacitive touchpad
+                // if there is a hit, delete the bubble from the dynamic array
+                if (true) bubbleLanes[0]->checkHit();
+                if (true) bubbleLanes[1]->checkHit();
+                if (true) bubbleLanes[2]->checkHit();
+                
+                // move down all the bubbles, deleting bubbles that are out of bounds if required
+                bubbleLanes[0]->moveDown();
+                bubbleLanes[1]->moveDown();
+                bubbleLanes[2]->moveDown();
+                
+                //this wait delay may need to be tuned
+                Thread::wait(100);
             }
-                
-                }
-        Thread::wait(100);    
+            
+            // uncomment this when gameplay works
+            //showScore();
+            
+            // return to homescreen when
+            songselect = false;
+            homescreen = true;
         }
+        Thread::wait(100);    
+    }
 }
-        
-