ECE 4180 @ Georgia Tech

Dependencies:   mbed mbed-rtos 4DGL-uLCD-SE MMA8452

Files at this revision

API Documentation at this revision

Comitter:
snorod
Date:
Thu Apr 30 01:01:47 2020 +0000
Parent:
9:f20983c914aa
Commit message:
Initial commit

Changed in this revision

MMA8452.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
mbed-rtos.lib Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MMA8452.lib	Thu Apr 30 01:01:47 2020 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/ashleymills/code/MMA8452/#a92a632a0cc7
--- a/main.cpp	Wed Oct 28 15:06:56 2015 +0000
+++ b/main.cpp	Thu Apr 30 01:01:47 2020 +0000
@@ -1,171 +1,409 @@
-// uLCD-144-G2 demo program for uLCD-4GL LCD driver library
-//
 #include "mbed.h"
 #include "uLCD_4DGL.h"
+#include "rtos.h"
+#include "MMA8452.h"
 
+#define LEFT_X 45
+#define CENTER_X 65
+#define RIGHT_X 85
+
+#define JUMP_Y 96
+#define CENTER_Y 108
+#define DUCK_Y 120
+
+#define RADIUS 4
+
+#define SPEED 5
+#define VOLUME 0.1
+
+Serial pc(USBTX,USBRX); // included for debugging accelerometer
+MMA8452 acc(p28, p27, 100000);
 uLCD_4DGL uLCD(p9,p10,p11); // serial tx, serial rx, reset pin;
+PwmOut jack(p23);
+DigitalIn jump_button(p22);
+DigitalIn duck_button(p21);
+
+// mutex for writing to the uLCD
+Mutex LCD;
+
+volatile int score;
+volatile int high_score;
+volatile int steps;
+volatile int strikes;
+double acc_x;
+volatile int player_x;
+volatile int player_y;
+
+volatile int obstacle_x;
+volatile int obstacle_y;
+volatile int dodge_x;
+
+int ob_x_roots[] = {61, 65, 69};
+const char* strikes_arr[4] = { "   ", "  X", " XX", "XXX" };
+enum ob_type {dodge, duck, jump};
+ob_type ob_type_arr[] = {dodge, duck, jump};
+
+volatile ob_type obstacle_type;
+
+volatile bool play_leftright;
+volatile bool play_jump;
+volatile bool play_duck;
+volatile bool play_strikes;
+volatile bool play_dead;
+
+void read_sound(void const *argument) {
+    while(1) {
+
+        // different sounds in order of priority to audio output
+        if (play_dead) {
+            jack.period(1.0/440.0);
+            jack = VOLUME/2.0;
+            Thread::wait(750);
+            jack = 0.0;
+            Thread::wait(100);
+            jack = VOLUME/2.0;
+            Thread::wait(750);
+            jack = 0.0;
+            Thread::wait(100);
+            jack = VOLUME/2.0;
+            Thread::wait(750);
+            jack = 0.0;
+            play_dead = false;
+            play_strikes = false;
+            play_duck = false;
+            play_jump = false;
+            play_leftright = false;
+        } else if (play_strikes) {
+            jack.period(1.0/440.0);
+            jack = VOLUME/2.0;
+            Thread::wait(750);
+            jack = 0.0;
+            play_strikes = false;
+            play_duck = false;
+            play_jump = false;
+            play_leftright = false;
+        } else if (play_duck) {
+            jack.period(1.0/130.8);
+            jack = VOLUME/2.0;
+            Thread::wait(1000);
+            jack = 0.0;
+            play_duck = false;
+            play_jump = false;
+            play_leftright = false;
+        } else if (play_jump) {
+            jack.period(1.0/261.6);
+            jack = VOLUME/2.0;
+            Thread::wait(150);
+            jack.period(1.0/523.3);
+            Thread::wait(300);
+            jack = 0.0;
+            play_jump = false;
+            play_leftright = false;
+        } else if (play_leftright) {
+            jack.period(1.0/261.6);
+            jack = VOLUME/2.0;
+            Thread::wait(250);
+            jack = 0.0;
+            play_leftright = false;
+        }
+    }
+}
+
+void read_acc(void const *argument){
+    while(1) {
+        acc.readXGravity(&acc_x);
+        if (acc_x > 0.5) {
+            if (player_x == CENTER_X) {
+                player_x = LEFT_X;
+            } else if (player_x == RIGHT_X) {
+                player_x = CENTER_X;
+            }
+            play_leftright = true;
+            Thread::wait(500);
+        } else if (acc_x < -0.5) {
+            if (player_x == CENTER_X) {
+                player_x = RIGHT_X;
+            } else if (player_x == LEFT_X) {
+                player_x = CENTER_X;
+            }
+            play_leftright = true;
+            Thread::wait(500);
+        }
+        Thread::wait(250);
+    }
+}
+
+void read_score(void const *argument) {
+    while(1) {
+        score = score + 10;
+        LCD.lock();
+        uLCD.locate(11, 0);
+        uLCD.printf("%7D", score); // maximum 7-digit score, cap at 9,999,900
+        LCD.unlock();
+        Thread::wait(1000);
+    }
+}
+
+void read_high_score(void const *argument) {
+    while(1) {
+        LCD.lock();
+        uLCD.locate(0, 0);
+        uLCD.printf("HIGH:\n%D", high_score);
+        LCD.unlock();
+        Thread::wait(1500);
+    }
+}
+
+void read_strikes(void const *argument) {
+    while(1) {
+        LCD.lock();
+        uLCD.locate(15, 1);
+        uLCD.printf(strikes_arr[strikes % 4]);
+        LCD.unlock();
+        Thread::wait(1000);
+    }
+}
+
+// check for button press
+void read_duck(void const *argument) {
+    while(1) {
+        if (!duck_button) {
+            player_y = DUCK_Y;
+            play_duck = true;
+            Thread::wait(1000);
+            player_y = CENTER_Y;
+        }
+    }
+}
+
+// check for button press
+void read_jump(void const *argument) {
+    while(1) {
+        if (!jump_button && player_y != DUCK_Y) {
+            player_y = JUMP_Y;
+            play_jump = true;
+            Thread::wait(1000);
+            if (player_y == JUMP_Y) {
+                player_y = CENTER_Y;
+            }
+        }
+    }
+}
+
+// check if it's game over
+void read_alive(void const *argument) {
+    while(1) {
+        if (strikes >= 3 || score >= 9999900) {
+            if (score > high_score) {
+                high_score = score;
+            }
+            score = 0;
+            strikes = 0;
+            player_x = CENTER_X;
+            player_y = CENTER_Y;
+        }
+    }
+}
+
+void read_position(void const *argument) {
+    while(1) {
+        LCD.lock();
+
+        // cover up positions on screen where there's no player or obstacle
+        if (player_x != LEFT_X) {
+            if (obstacle_y != JUMP_Y) {
+                uLCD.filled_circle(LEFT_X, JUMP_Y, RADIUS, 0x003057);
+            }
+            if (obstacle_y != CENTER_Y) {
+                uLCD.filled_circle(LEFT_X, CENTER_Y, RADIUS, 0x003057);
+            }
+            if (obstacle_y != DUCK_Y) {
+                uLCD.filled_circle(LEFT_X, DUCK_Y, RADIUS, 0x003057);
+            }
+        }
+        if (player_x != CENTER_X) {
+            if (obstacle_y != JUMP_Y) {
+                uLCD.filled_circle(CENTER_X, JUMP_Y, RADIUS, 0x003057);
+            }
+            if (obstacle_y != CENTER_Y) {
+                uLCD.filled_circle(CENTER_X, CENTER_Y, RADIUS, 0x003057);
+            }
+            if (obstacle_y != DUCK_Y) {
+                uLCD.filled_circle(CENTER_X, DUCK_Y, RADIUS, 0x003057);
+            }
+        }
+        if (player_x != RIGHT_X) {
+            if (obstacle_y != JUMP_Y) {
+                uLCD.filled_circle(RIGHT_X, JUMP_Y, RADIUS, 0x003057);
+            }
+            if (obstacle_y != CENTER_Y) {
+                uLCD.filled_circle(RIGHT_X, CENTER_Y, RADIUS, 0x003057);
+            }
+            if (obstacle_y != DUCK_Y) {
+                uLCD.filled_circle(RIGHT_X, DUCK_Y, RADIUS, 0x003057);
+            }
+        }
+        if (player_y != JUMP_Y && obstacle_y != JUMP_Y) {
+            if (player_x == RIGHT_X) {
+                uLCD.filled_circle(player_x, JUMP_Y, RADIUS, 0x003057);
+            } else if (player_x == LEFT_X) {
+                uLCD.filled_circle(player_x, JUMP_Y, RADIUS, 0x003057);
+            } else if (player_x == CENTER_X) {
+                uLCD.filled_circle(player_x, JUMP_Y, RADIUS, 0x003057);
+            }
+        }
+        if (player_y != CENTER_Y && obstacle_y != CENTER_Y) {
+            uLCD.filled_circle(player_x, CENTER_Y, RADIUS, 0x003057);
+        }
+        if (player_y != DUCK_Y && obstacle_y != DUCK_Y) {
+            if (player_x == RIGHT_X) {
+                uLCD.filled_circle(player_x, DUCK_Y, RADIUS, 0x003057);
+            } else if (player_x == LEFT_X) {
+                uLCD.filled_circle(player_x, DUCK_Y, RADIUS, 0x003057);
+            } else if (player_x == CENTER_X) {
+                uLCD.filled_circle(player_x, DUCK_Y, RADIUS, 0x003057);
+            }
+        }
+        uLCD.filled_circle(player_x, player_y, RADIUS, 0xB3A369);
+        LCD.unlock();
+    }
+}
+
+void read_obstacle(void const *argument) {
+    while(1) {
+        LCD.lock();
+        uLCD.filled_rectangle(obstacle_x - 10 - (steps * 2), obstacle_y + 7, obstacle_x + 10 + (steps * 2), obstacle_y - 7, 0x003057);
+        steps++;
+        obstacle_y = obstacle_y + 12;
+
+        // move obstacle along slope down the track
+        if (obstacle_type == dodge) {
+            if (dodge_x >= ob_x_roots[2]) {
+                dodge_x = dodge_x + 2;
+            } else if (dodge_x <= ob_x_roots[0]) {
+                dodge_x = dodge_x - 2;
+            }
+        }
+
+        // reset obstacle if it has exited the screen
+        if (obstacle_y >= 130) {
+            obstacle_type = ob_type_arr[rand() % 3];
+            obstacle_x = ob_x_roots[1];
+            if (obstacle_type == dodge) {
+                dodge_x = ob_x_roots[rand() % 3];
+            }
+            obstacle_y = 12;
+            steps = 0;
+        }
+
+        // draw dodge obstacle
+        if (obstacle_type != dodge) {
+            uLCD.filled_rectangle(obstacle_x - 10 - (steps * 2), obstacle_y + 7, obstacle_x + 10 + (steps * 2), obstacle_y - 7, 0xEAAA00);
+        } else {
+            if (dodge_x >= ob_x_roots[2]) {
+                // draw rectangle on left side, dodge on the right
+                uLCD.filled_rectangle(obstacle_x - 10 - (steps * 2), obstacle_y + 7, dodge_x - 10, obstacle_y - 7, 0xEAAA00);
+            } else if (dodge_x <= ob_x_roots[0]) {
+                // draw rectangle on right side, dodge on the left
+                uLCD.filled_rectangle(dodge_x + 10, obstacle_y + 7, obstacle_x + 10 + (steps * 2), obstacle_y - 7, 0xEAAA00);
+            } else {
+                // draw two rectangles on either side, dodge in the middle
+                uLCD.filled_rectangle(ob_x_roots[0] - 5 - (steps * 2), obstacle_y + 7, ob_x_roots[0] - steps, obstacle_y - 7, 0xEAAA00);
+                uLCD.filled_rectangle(ob_x_roots[2] + steps, obstacle_y + 7, ob_x_roots[2] + 5 + (steps * 2), obstacle_y - 7, 0xEAAA00);
+            }
+        }
+
+        // draw duck/jump obstacle
+        if (obstacle_type == duck) {
+            uLCD.filled_rectangle(obstacle_x - 8 - (steps * 2), obstacle_y + 7, obstacle_x + 8 + (steps * 2), obstacle_y - 5, 0x003057);
+        } else if (obstacle_type == jump) {
+            uLCD.filled_rectangle(obstacle_x - 8 - (steps * 2), obstacle_y + 5, obstacle_x + 8 + (steps * 2), obstacle_y - 7, 0x003057);
+        }
+
+        // check for collisions, increment strikes if so
+        if (obstacle_y == CENTER_Y) {
+            if ((obstacle_type == duck && player_y != DUCK_Y) || (obstacle_type == jump && player_y != JUMP_Y) || (obstacle_type == dodge && dodge_x != player_x)) {
+                strikes++;
+                if (strikes >= 3) {
+                    play_dead = true;
+                } else {
+                    play_strikes = true;
+                }
+            }
+        }
+        LCD.unlock();
+        Thread::wait(SPEED);
+    }
+}
 
 int main()
 {
-    // basic printf demo = 16 by 18 characters on screen
-    uLCD.printf("\nHello uLCD World\n"); //Default Green on black text
-    uLCD.printf("\n  Starting Demo...");
-    uLCD.text_width(4); //4X size text
-    uLCD.text_height(4);
-    uLCD.color(RED);
-    for (int i=10; i>=0; --i) {
-        uLCD.locate(1,2);
-        uLCD.printf("%2D",i);
-        wait(.5);
-    }
-    uLCD.cls();
-    uLCD.printf("Change baudrate......");
-    uLCD.baudrate(3000000); //jack up baud rate to max for fast display
-    //if demo hangs here - try lower baud rates
-    //
-    // printf text only full screen mode demo
-    uLCD.background_color(BLUE);
-    uLCD.cls();
-    uLCD.locate(0,0);
-    uLCD.color(WHITE);
-    uLCD.textbackground_color(BLUE);
-    uLCD.set_font(FONT_7X8);
-    uLCD.text_mode(OPAQUE);
-    int i=0;
-    while(i<64) {
-        if(i%16==0) uLCD.cls();
-        uLCD.printf("TxtLine %2D Page %D\n",i%16,i/16 );
-        i++; //16 lines with 18 charaters per line
-    }
-    wait(0.5);
-    //demo graphics commands
-    uLCD.background_color(BLACK);
+    uLCD.background_color(0x003057);
     uLCD.cls();
-    uLCD.background_color(DGREY);
-    uLCD.filled_circle(60, 50, 30, 0xFF00FF);
-    uLCD.triangle(120, 100, 40, 40, 10, 100, 0x0000FF);
-    uLCD.line(0, 0, 80, 60, 0xFF0000);
-    uLCD.filled_rectangle(50, 50, 100, 90, 0x00FF00);
-    uLCD.pixel(60, 60, BLACK);
-    uLCD.read_pixel(120, 70);
-    uLCD.circle(120, 60, 10, BLACK);
-    uLCD.set_font(FONT_7X8);
-    uLCD.text_mode(TRANSPARENT);
-    uLCD.text_bold(ON);
-    uLCD.text_char('B', 9, 8, BLACK);
-    uLCD.text_char('I',10, 8, BLACK);
-    uLCD.text_char('G',11, 8, BLACK);
-    uLCD.text_italic(ON);
-    uLCD.text_string("This is a test of string", 1, 4, FONT_7X8, WHITE);
-    wait(2);
+    uLCD.text_width(4);
+    uLCD.text_height(4);
+    uLCD.textbackground_color(0x003057);
+    uLCD.color(0xB3A369);
+    uLCD.printf("\nBuzz Run");
 
-//Bouncing Ball Demo
-    float fx=50.0,fy=21.0,vx=1.0,vy=0.4;
-    int x=50,y=21,radius=4;
-    uLCD.background_color(BLACK);
-    uLCD.cls();
-    //draw walls
-    uLCD.line(0, 0, 127, 0, WHITE);
-    uLCD.line(127, 0, 127, 127, WHITE);
-    uLCD.line(127, 127, 0, 127, WHITE);
-    uLCD.line(0, 127, 0, 0, WHITE);
-    for (int i=0; i<1500; i++) {
-        //draw ball
-        uLCD.filled_circle(x, y, radius, RED);
-        //bounce off edge walls and slow down a bit?
-        if ((x<=radius+1) || (x>=126-radius)) vx = -.90*vx;
-        if ((y<=radius+1) || (y>=126-radius)) vy = -.90*vy;
-        //erase old ball location
-        uLCD.filled_circle(x, y, radius, BLACK);
-        //move ball
-        fx=fx+vx;
-        fy=fy+vy;
-        x=(int)fx;
-        y=(int)fy;
-    }
-    wait(0.5);
-//draw an image pixel by pixel
-    int pixelcolors[50][50];
-    uLCD.background_color(BLACK);
+    wait(2);
     uLCD.cls();
-//compute Mandelbrot set image for display
-//image size in pixels
-    const unsigned ImageHeight=128;
-    const unsigned ImageWidth=128;
-    //"c" region to display
-    double MinRe = -0.75104;
-    double MaxRe = -0.7408;
-    double MinIm = 0.10511;
-    double MaxIm = MinIm+(MaxRe-MinRe)*ImageHeight/ImageWidth;
-    double Re_factor = (MaxRe-MinRe)/(ImageWidth-1);
-    double Im_factor = (MaxIm-MinIm)/(ImageHeight-1);
-    unsigned MaxIterations = 2048;
-    for(unsigned y=0; y<ImageHeight; ++y) {
-        double c_im = MaxIm - y*Im_factor;
-        for(unsigned x=0; x<ImageWidth; ++x) {
-            double c_re = MinRe + x*Re_factor;
-            double Z_re = c_re, Z_im = c_im;
-            int niterations=0;
-            for(unsigned n=0; n<MaxIterations; ++n) {
-                double Z_re2 = Z_re*Z_re, Z_im2 = Z_im*Z_im;
-                if(Z_re2 + Z_im2 > 4) {
-                    niterations = n;
-                    break;
-                }
-                Z_im = 2*Z_re*Z_im + c_im;
-                Z_re = Z_re2 - Z_im2 + c_re;
-            }
-            if (niterations!=(MaxIterations-1))
-                uLCD.pixel(x,y,((niterations & 0xF00)<<12)+((niterations & 0xF0)<<8)+((niterations & 0x0F)<<4) );
-        }
+    uLCD.baudrate(3000000); // high baud rate for fast refresh
+
+    // Left-side guardrails
+    uLCD.line(23, 130, 43, 10, 0xFFFFFF);
+    uLCD.line(24, 130, 44, 10, 0xB3A369);
+    uLCD.line(25, 130, 45, 10, 0xB3A369);
+    uLCD.line(26, 130, 46, 10, 0xB3A369);
+    uLCD.line(27, 130, 47, 10, 0xFFFFFF);
+
+    // Right-side guardrails
+    uLCD.line(103, 130, 83, 10, 0xFFFFFF);
+    uLCD.line(104, 130, 84, 10, 0xB3A369);
+    uLCD.line(105, 130, 85, 10, 0xB3A369);
+    uLCD.line(106, 130, 86, 10, 0xB3A369);
+    uLCD.line(107, 130, 87, 10, 0xFFFFFF);
+
+    score = 0;
+    high_score = 0;
+    strikes = 0;
+    steps = 0;
+
+    // make sure sounds are off
+    play_leftright = false;
+    play_jump = false;
+    play_duck = false;
+    play_strikes = false;
+    play_dead = false;
+
+    // initialize player position
+    player_x = CENTER_X;
+    player_y = CENTER_Y;
+
+    // initialize obstacle coordinates
+    obstacle_x = ob_x_roots[1];
+    dodge_x = ob_x_roots[rand() % 3];
+    obstacle_y = 12;
+    obstacle_type = ob_type_arr[rand() % 3];
+
+    // pull up push_buttons
+    jump_button.mode(PullUp);
+    duck_button.mode(PullUp);
+
+    // start threads
+    Thread acc_thread(read_acc);
+    Thread score_thread(read_score);
+    Thread duck_thread(read_duck);
+    Thread jump_thread(read_jump);
+    Thread alive_thread(read_alive);
+    Thread position_thread(read_position);
+    Thread obstacle_thread(read_obstacle);
+    Thread strikes_thread(read_strikes);
+    Thread sound_thread(read_sound);
+    Thread high_score_thread(read_high_score);
+
+    while(1) {
+        // loop forever
     }
-    wait(5);
-// PLASMA wave BLIT animation
-//draw an image using BLIT (Block Image Transfer) fastest way to transfer pixel data
-    uLCD.cls();
-    int num_cols=50;
-    int num_rows=50;
-    int frame=0;
-    double a,b,c=0.0;
-    while(frame<75) {
-        for (int k=0; k<num_cols; k++) {
-            b= (1+sin(3.14159*k*0.75/(num_cols-1.0)+c))*0.5;
-            for (int i=0; i<num_rows; i++) {
-                a= (1+sin(3.14159*i*0.75/(num_rows-1.0)+c))*0.5;
-                // a and b will be a sine wave output between 0 and 1
-                // sine wave was scaled for nice effect across array
-                // uses a and b to compute pixel colors based on rol and col location in array
-                // also keeps colors at the same brightness level
-                if ((a+b) <.667)
-                    pixelcolors[i][k] =  (255-(int(254.0*((a+b)/0.667)))<<16) | (int(254.0*((a+b)/0.667))<<8) | 0;
-                else if ((a+b)<1.333)
-                    pixelcolors[i][k] = (0 <<16) | (255-(int (254.0*((a+b-0.667)/0.667)))<<8) | int(254.0*((a+b-0.667)/0.667));
-                else
-                    pixelcolors[i][k] = (int(255*((a+b-1.333)/0.667))<<16) | (0<<8)  | (255-(int (254.0*((a+b-1.333)/0.667))));
-            }
-        }
-        uLCD.BLIT(39, 39, 50, 50, &pixelcolors[0][0]);
-        c = c + 0.0314159*3.0;
-        if (c > 6.2831) c = 0.0;
-        frame++;
-    }
-    //Load Image Demo
-    uLCD.cls();
-    //SD card needed with image and video files for last two demos
-    uLCD.cls();
-    uLCD.media_init();
-    uLCD.printf("\n\nAn SD card is needed for image and video data");
-    uLCD.set_sector_address(0x001D, 0x4C01);
-    uLCD.display_image(0,0);
-    wait(10);
-    //Play video demo
-    while(1) {
-        uLCD.cls();
-        uLCD.media_init();
-        uLCD.set_sector_address(0x001D, 0x4C42);
-        uLCD.display_video(0,0);
-    }
+
 }
-
-
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-rtos.lib	Thu Apr 30 01:01:47 2020 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/teams/ST/code/mbed-rtos/#83895f30f8f2