4180 Final

Dependencies:   mbed wave_player mbed-rtos 4180Final SDFileSystem

main.cpp

Committer:
trmontgomery
Date:
2020-04-29
Revision:
20:a46d5d9c21cd
Parent:
19:537afb30777c
Child:
21:3421fe64e28c

File content as of revision 20:a46d5d9c21cd:

#include "mbed.h"
#include "uLCD_4DGL.h"
#include "Nav_Switch.h"
#include "SDFileSystem.h"
#include "microphone.h"
#include "fireflies.h"
#include "wave_player.h"
#include  "rtos.h"

//macros for specs of spi and ledstrip
#define LED_NUM 18
#define LED_GLOBAL 31 // brightness 0-31
#define LED_FREQ 500000 // spi

//Hardware Init
Nav_Switch myNav(p21, p22, p23, p24, p25); //pin order on Sparkfun breakout
uLCD_4DGL uLCD(p28, p27, p30); // serial tx, serial rx, reset pin; 
SDFileSystem sd(p11, p12, p13, p10, "sd");
microphone mymic1(p15);
microphone mymic2(p17);
AnalogIn pot(p16);
AnalogOut DACout(p18);
PwmOut myled(LED1);
PwmOut myled2(LED2);
PwmOut myled3(LED3);
SPI spi(p5, p6, p7);


//GLOBALS
volatile bool stopLedStrip = false; //bool to check if ledstrip is done recieving frame before terminating thread

//Mutexs
Mutex lcd_mutex;
Mutex lightLEDS_mutex;

int rounds = 3;
int curRound = 1;
volatile int score1 = 0;
volatile int score2 = 0;
int scores1[7] = {0};
int scores2[7] = {0};
int curTime = 0;
int wonRnds1 = 0;
int wonRnds2 = 0;
int highScoresArr[10] = {100, 90, 83, 73, 64, 54, 44, 34, 24, 14};
int s = 0;
int timer = 0;
volatile int micScore1 = 0;
volatile int micScore2 = 0;
int playType = 0;
Thread thread1, thread2, t1, t2, t3;

int ledArr[LED_NUM] = {0};

// Stuff for sound
unsigned char *music = NULL;
wave_player waver(&DACout);
Ticker nextsample;
volatile int sIndx = 0;
int playMusic = 0;

//stuff for play
int mic_reading1 = 0; 
int mic_reading2 = 0; 
float mic_read_raw = 0; 
Ticker mic; 
Timer round; 
int round_time = 25;
int loud1 = 0; 
int loud2 = 0; 

int main();
void play();


// Method for ticker for sound
void playMenuMusic() {
    if (playMusic) {
        music = (unsigned char*) fireflies;
        DACout.write(music[sIndx++] / 255.0);
        if(sIndx > 120000) {
            sIndx = 0;
        }
    } else {
        DACout.write(0.0);
        sIndx = 0;
    }
}


void clearVals() {
    score1 = 0;
    score2 = 0;
    wonRnds1 = 0;
    wonRnds2 = 0;
    curRound = 1;
    curTime = 0;
    for (int i=0; i<sizeof(scores1)/4; i++) {
        scores1[i] = 0;
        scores2[i] = 0;
    }
}

void saveHS() {
    mkdir("/sd/finalProj", 0777);
    FILE *fp = fopen("/sd/finalProj/highscores.txt", "w");
    if(fp == NULL) {
     uLCD.printf("Error Open \n");
    }
    for (int i=0; i<sizeof(highScoresArr)/4; i++) {
        fprintf(fp, "%4d", highScoresArr[i]);
    }
    fclose(fp);
}
//reset the led strip to no lit leds
void resetLedStrip() {
    int i;
    // start frame
    for (i = 0; i < 4; i ++) {
        spi.write(0);
    }
    for (i = 0; i < LED_NUM; i ++) {
        spi.write((7<<5) | LED_GLOBAL);
        spi.write(0x00); // B
        spi.write(0x00); // G
        spi.write(0x00); // R
    }
    //end frame
    for (i = 0; i < 4; i ++) {
        spi.write(1);
    }
}

//0 out the led array
void resetLedArr(){
    for(int i = 0; i < LED_NUM; i++){    
    ledArr[i] = 0;
    }
} 

void gameOver() {
    resetLedArr();
    resetLedStrip();
    uLCD.filled_rectangle(13, 25, 115, 120, LRED);
    // header
    uLCD.color(BLACK);
    uLCD.text_height(2);
    uLCD.text_width(2);
    uLCD.textbackground_color(LRED);
    uLCD.locate(1,2);
    uLCD.printf("Results");
    uLCD.locate(1,3);
    uLCD.color(DGOLD);
    uLCD.printf("Winner:");
    uLCD.filled_rectangle(13, 47, 115, 48, RED);
    uLCD.text_height(3);
    uLCD.text_width(3);
    // get total scores
    int total1 = 0;
    int total2 = 0;
    for (int i=0; i<sizeof(scores1)/4; i++) {
        total1 += scores1[i];
        total2 += scores2[i];
    }
    int avg1 = total1 / rounds;
    int avg2 = total2 / rounds;
    // Save new high scores if needed
    // ---- Player1 ----
    int indx = -1;
    for (int i=0; i<sizeof(highScoresArr)/4; i++) {
        if (avg1 > highScoresArr[i]) {
            indx = i;
            break;
        }
    }
    // Save new highscore
    if (indx != -1) {
        for (int i=sizeof(highScoresArr)/4-1; i>indx; i--) {
            highScoresArr[i] = highScoresArr[i-1];
        }
        highScoresArr[indx] = avg1;
        saveHS();  // Save highScoresArr to SD card
    }
    // ---- End P1 ----
    // ---- Player2 ----
    indx = -1;
    for (int i=0; i<sizeof(highScoresArr)/4; i++) {
        if (avg2 > highScoresArr[i]) {
            indx = i;
            break;
        }
    }
    // Save new highscore
    if (indx != -1) {
        for (int i=sizeof(highScoresArr)/4-1; i>indx; i--) {
            highScoresArr[i] = highScoresArr[i-1];
        }
        highScoresArr[indx] = avg2;
        saveHS();  // Save highScoresArr to SD card
    }
    // ---- End P2 ----
    // Print winner info to screen
    if (wonRnds1 > wonRnds2) {
        uLCD.color(BLUE);
        uLCD.locate(2,3);
        uLCD.printf("P1");
        uLCD.text_height(1);
        uLCD.text_width(1);
        uLCD.locate(3,12);
        uLCD.printf("Rounds won: %1d", wonRnds1);
        uLCD.locate(5,13);
        uLCD.printf("Avg: %4d", avg1);
        
    } else if (wonRnds2 > wonRnds1) {
        uLCD.color(PURPLE);
        uLCD.locate(2,3);
        uLCD.printf("P2");
        uLCD.text_height(1);
        uLCD.text_width(1);
        uLCD.locate(3,12);
        uLCD.printf("Rounds won: %1d", wonRnds2);
        uLCD.locate(5,13);
        uLCD.printf("Avg: %4d", avg2);
    } else {
        uLCD.locate(2,3);
        uLCD.color(BLACK);
        uLCD.printf("Tie");
    }
    uLCD.text_height(3);
    uLCD.text_width(3);
    while (1) {
        timer = 0;
         while (timer<80) {
             if (myNav.fire()) {
                // clear values
                clearVals();
                main();
             }
             // Blink winner
             if (timer == 0) {
                if (wonRnds1 > wonRnds2) {
                    uLCD.color(BLUE);
                    uLCD.locate(2,3);
                    uLCD.printf("P1");
                } else if (wonRnds2 > wonRnds1) {
                    uLCD.color(PURPLE);
                    uLCD.locate(2,3);
                    uLCD.printf("P2");
                } else {
                    uLCD.locate(2,3);
                    uLCD.color(BLACK);
                    uLCD.printf("Tie");
                }
             } else if (timer == 60) {
                 uLCD.color(LRED);
                 uLCD.locate(2,3);
                 uLCD.printf("CLS");
             }
             wait(.01);
             timer++;
         }
    }
}

void nextRound() {
    uLCD.filled_rectangle(13, 25, 115, 120, LRED);
    // header
    uLCD.color(BLACK);
    uLCD.text_height(2);
    uLCD.text_width(2);
    uLCD.textbackground_color(LRED);
    uLCD.locate(2,2);
    uLCD.printf("ROUND%1d", curRound);
    uLCD.locate(1,3);
    uLCD.color(DGOLD);
    uLCD.printf("Winner:");
    uLCD.filled_rectangle(13, 47, 115, 48, RED);
    uLCD.text_height(3);
    uLCD.text_width(3);
    if (score1 > score2) {
        uLCD.color(BLUE);
        uLCD.locate(2,3);
        uLCD.printf("P1");
        uLCD.locate(1,4);
        uLCD.printf("%4d", score1);
        wonRnds1++;
    } else if (score2 > score1) {
        uLCD.color(PURPLE);
        uLCD.locate(2,3);
        uLCD.printf("P2");
        uLCD.locate(1,4);
        uLCD.printf("%4d", score2);
        wonRnds2++;
    } else {
        uLCD.locate(2,4);
        uLCD.printf("Tie");
    }
    scores1[curRound-1] = score1;
    scores2[curRound-1] = score2;
    wait(3.0);
    curRound++;
    curTime = 0;
    score1 = 0;
    score2 = 0;
    if (curRound > rounds) {
        gameOver();
    }
    play();
}

void pause() {
    uLCD.filled_rectangle(13, 25, 115, 120, LRED);
    uLCD.filled_rectangle(13, 48, 115, 50, RED);
    // header
    uLCD.color(BLACK);
    uLCD.text_height(2);
    uLCD.text_width(2);
    uLCD.textbackground_color(LRED);
    uLCD.locate(2,2);
    uLCD.printf("PAUSED");
    // Choices
    uLCD.text_height(1);
    uLCD.text_width(1);
    uLCD.locate(5,8);
    uLCD.printf("Continue");
    uLCD.locate(7,11);
    uLCD.printf("Quit");
    // Selector dots
    int xPos[2] = {30, 44};
    int yPos[2] = {67, 91};
    int ticker = 0;
    int oldTicker = 1;
    for (int i=0; i<sizeof(yPos)/4; i++) {
        uLCD.filled_circle(xPos[i], yPos[i], 1+s, RED);
    }
    while (1) {
         // Fill selector circle and if necessary, clear old
         if (oldTicker != ticker) {
            uLCD.filled_circle(xPos[oldTicker], yPos[oldTicker], 3+s, LRED);
            uLCD.filled_circle(xPos[oldTicker], yPos[oldTicker], 1+s, RED);
         }
         uLCD.filled_circle(xPos[ticker], yPos[ticker], 3+s, RED);
         // save oldTicker spot
         oldTicker = ticker;
         // get new ticker position
         timer = 0;
         while (timer<100) {
             if (timer == 0) {
                 uLCD.filled_circle(xPos[ticker], yPos[ticker], 3+s, RED);
             } else if (timer == 70) {
                 uLCD.filled_circle(xPos[ticker], yPos[ticker], 3+s, LRED);
             }
             if (myNav.fire()) {
                 uLCD.filled_circle(xPos[ticker], yPos[ticker], 2+s, GREEN);
                 switch(ticker) {
                     case 0:
                        play();
                        break;
                     case 1:
                        clearVals();
                        main();
                  }
             } else if (myNav.up() || myNav.left()) {
                 wait(.2);
                 ticker = ticker - 1;
                 if (ticker < 0) {
                     ticker = sizeof(xPos)/4 - 1;
                 }
             } else if (myNav.down() || myNav.right()) {
                 wait(.2);
                 ticker = (ticker + 1) % (sizeof(xPos)/4);
             }
             wait(.01);
             timer++;
         }
    }
}
// thread that updates the score displayed on lcd
void update_lcd_score() {
    while(1){
        myled = 1;// testing to see if threads are called
    lcd_mutex.lock();
    uLCD.color(BLUE);
    uLCD.locate(0,1);
    uLCD.printf("%4d", mic_reading1);
    //uLCD.printf("%4d", score1);
    uLCD.color(PURPLE);
    uLCD.locate(0,3);
    uLCD.printf("%4d", mic_reading2);
    //uLCD.printf("%4d", score2);
    lcd_mutex.unlock();
      
    }
}

    
//new update led function
void dotStar () {
    int i = 0;
    while(1){
    // start frame
    for (i = 0; i < 4; i ++) {
        spi.write(0);
    }
    // led frame
    lightLEDS_mutex.lock();
    for (i = 0; i < LED_NUM; i ++) {
            if(ledArr[i] == 1)
            {
            // blue color for p1 leds 
            spi.write((7<<5) | LED_GLOBAL);
            spi.write(0xff); // B
            spi.write(0x00); // G
           spi.write(0x00); // R
           // spi.write((led_buf[i] >> 8) & 0xff); // G
           //spi.write(led_buf[i] & 0xff); // R
            }
            else if (ledArr[i] == 2){
            //green color for p2 leds
             spi.write((7<<5) | LED_GLOBAL);
            spi.write(0x00); // B
            spi.write(0xff); // G
           spi.write(0x00); // R
            // spi.write((7<<5) | LED_GLOBAL);
            // spi.write((led_buf[i] >> 16) & 0xff); // B
            // spi.write((led_buf[i] >> 8) & 0xff); // G
            // spi.write(led_buf[i] & 0xff); // R
            }
           else if(ledArr[i] == 0)
           {
            //no color for leds that are not lit by any player.
            spi.write((7<<5) | LED_GLOBAL);
            spi.write(0x00); // B
            spi.write(0x00); // G
            spi.write(0x00); // R
            // spi.write((led_buf[i] >> 16) & 0xff); // B
            // spi.write((led_buf[i] >> 8) & 0xff); // G
            // spi.write(led_buf[i] & 0xff); // R

           }
    }
    lightLEDS_mutex.unlock();
    // end frame
    for (i = 0; i < 4; i ++) {
        spi.write(1);
    }
    if(stopLedStrip)
    {
     break;
     }   
    Thread::wait(200);
    }
}


void update_ledArr() {
    lightLEDS_mutex.lock();
    //for loop p1
    for(int i = 0; i < LED_NUM; i++) {
        if((ledArr[i] == 0) && (score1 % 4 == 0)) //updates led when score is multiply of 4
        {
            ledArr[i] = 1;
            break;
        }
        else if ((ledArr[i] == 2) && (score1 % 4 == 0) && (score1 > score2)) //updates when
        {
            ledArr[i] = 1;
            break;
        }    
    }

    //for loop for p2
    for(int i = LED_NUM -1 ; i >= 0 ; i--) {
        if((ledArr[i] == 0) && (score2 % 4 == 0)) //updates led when score is multiply of 4
        {
            ledArr[i] = 2;
            break;
        }
        else if ((ledArr[i] == 1) && (score2 % 4 == 0) && (score2 > score1)) 
        {
            ledArr[i] = 2;
            break;
        }    
    }

    lightLEDS_mutex.unlock();
}


void update_score(){
    if (mic_reading1 > 30) {
        loud1++; //if the player screams loudly for enough times it increases your score
        score1++;
    }
    if (mic_reading2 > 30) {
        loud2++;
        score2++; 
    }
}

   
void read_mic(){
    while(1){
        mic_reading1 = int(abs((mymic1 - (0.67/3.3)))*500.0); //this value should hover around 15 
        mic_reading2 = int(abs((mymic2 - (0.67/3.3)))*500.0) + 20; 
        update_score();
        update_ledArr(); //updates an array that tells what led should be on

        Thread::wait(500);
    }
}


void play() {
     srand(time(NULL));
     stopLedStrip = false; // let ledstrip recieve frames
     uLCD.background_color(GREEN);
     uLCD.cls();
     uLCD.filled_rectangle(0, 0, 200, 15, RED);
     // header
     uLCD.color(BLACK);
     uLCD.locate(5,0);
     uLCD.text_height(2);
     uLCD.text_width(2);
     uLCD.textbackground_color(RED);
     uLCD.printf("PLAY");
     uLCD.text_height(1);
     uLCD.text_width(1);
     uLCD.locate(14,1);
     uLCD.printf("Rnd%1d", curRound);
     // Scores headers
     uLCD.textbackground_color(GREEN);
     uLCD.color(BLUE);
     uLCD.locate(5,3);
     uLCD.printf("Player 1:");
     uLCD.color(PURPLE);
     uLCD.locate(5,11);
     uLCD.printf("Player 2:");
     // Scores
     uLCD.text_height(4);
     uLCD.text_width(4);
     wait(0.5);
     //reset ledstrip
     resetLedArr();
     resetLedStrip();
     
     t1.start(read_mic);
     t2.start(update_lcd_score);
     t3.start(dotStar); //new thread that sends frames to led strip
     
    
     while (1) {
        timer = 0;
        // Blinking pause button
        while (timer<25) {
            if (myNav.fire()) {
                lcd_mutex.lock();
                uLCD.filled_rectangle(60, 68, 65, 82, GREEN);
                uLCD.filled_rectangle(70, 68, 75, 82, GREEN);
                wait(.1);
                
                stopLedStrip = true;
                lcd_mutex.unlock();
                t1.terminate();
                t2.terminate();
                t1.join();
                t2.join();
                t3.join();
               
                stopLedStrip = false;
                myled=0;
                pause();
            }
            lcd_mutex.lock(); //remove if thread doesnt work
            if (timer % 25 == 0) {
                // Time bar
                double roundTime = 7.0;  // in secs
                int length = (int) ( (double)curTime / roundTime * 127.0);
                uLCD.filled_rectangle(0, 65, length, 85, DGREEN);
                if (length >= 127) {
                    stopLedStrip = true; // wait for ledstrip to recieve last frame before termianting thread
                    t1.terminate();
                    t2.terminate();
                    t1.join();
                    t2.join();
                    t3.join();
                    myled = 0;
                    lcd_mutex.unlock();
                    stopLedStrip = false;
                    nextRound();
                }
                curTime++;
            }
            if (timer < 20){
                uLCD.filled_rectangle(60, 68, 65, 82, LGREY);
                uLCD.filled_rectangle(70, 68, 75, 82, LGREY);
            } else if (timer >= 20) {
                uLCD.filled_rectangle(60, 68, 65, 82, BLACK);
                uLCD.filled_rectangle(70, 68, 75, 82, BLACK);
            }
            lcd_mutex.unlock();
            Thread::wait(100);
            timer++;
         }
     }
}

void highScores() {
     uLCD.background_color(ORANGE);
     uLCD.cls();
     uLCD.filled_rectangle(0, 0, 200, 14, RED);
     uLCD.color(BLACK);
     uLCD.locate(0,0);
     uLCD.text_height(2);
     uLCD.text_width(2);
     uLCD.textbackground_color(RED);
     uLCD.printf("HighScore");
     uLCD.line(0, 14, 200, 14, RED);
     uLCD.line(0, 15, 200, 15, RED);
     uLCD.text_height(1);
     uLCD.text_width(1);
     uLCD.locate(7,14);
     uLCD.color(BLACK);
     uLCD.textbackground_color(ORANGE);
     uLCD.printf("Back");
     uLCD.color(BLUE);
     int rank[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
     for (int i=0; i<sizeof(rank)/4; i++) {
         uLCD.locate(1,i+2);
         uLCD.printf("Position %2d: %4d", rank[i], highScoresArr[i]);
     }
     while (1) {
        timer = 0;
         while (timer<50) {
             if (timer < 30){
                 uLCD.filled_circle(45, 115, 3+s, RED);
             } else {
                 uLCD.filled_circle(45, 115, 3+s, ORANGE);
             }
             if (myNav.fire()) {
                 uLCD.filled_circle(45, 115, 2+s, GREEN);
                 wait(.1);
                 main();
             }
             wait(.01);
             timer++;
         }
     }
}

void settings() {
     uLCD.background_color(LGREY);
     uLCD.cls();
     uLCD.filled_rectangle(0, 0, 200, 15, RED);
     uLCD.color(BLACK);
     uLCD.locate(1,0);
     uLCD.text_height(2);
     uLCD.text_width(2);
     uLCD.textbackground_color(RED);
     uLCD.printf("Settings");
     // Rounds to play
     uLCD.text_height(1);
     uLCD.text_width(1);
     uLCD.locate(0,2);
     uLCD.color(BLUE);
     uLCD.textbackground_color(LGREY);
     uLCD.printf("Choose how many   rounds to play:");
     uLCD.locate(9,4);
     uLCD.color(BLUE);
     uLCD.printf("3");
     uLCD.locate(9,5);
     uLCD.printf("5");
     uLCD.locate(9,6);
     uLCD.printf("7");
     uLCD.locate(4,7);
     uLCD.line(0, 32, 200, 32, BLUE);
     uLCD.printf("Rounds = %1d", rounds);
     // Number of players
     uLCD.color(DGREEN);
     uLCD.locate(0,9);
     uLCD.printf("Choose how many   players:");
     uLCD.locate(9,11);
     uLCD.printf("1");
     uLCD.locate(9,12);
     uLCD.printf("2");
     uLCD.locate(4,13);
     uLCD.line(0, 88, 200, 88, DGREEN);
     uLCD.printf("Players = %1d", playType+1);
     // Back
     uLCD.locate(7,15);
     uLCD.color(BLACK);
     uLCD.printf("Back");
     uLCD.baudrate(BAUD_3000000); //jack up baud rate to max for fast display
     int xPos[6] = {57, 57, 57, 57, 57, 45};
     int yPos[6] = {36, 42, 50, 91, 99, 123};
     int ticker = 0;
     int oldTicker = 1;
     for (int i=0; i<sizeof(yPos)/4; i++) {
         uLCD.filled_circle(xPos[i], yPos[i], 1+s, RED);
     }
     while (1) {
         // Fill selector circle and if necessary, clear old
         if (oldTicker != ticker) {
            uLCD.filled_circle(xPos[oldTicker], yPos[oldTicker], 3+s, LGREY);
            uLCD.filled_circle(xPos[oldTicker], yPos[oldTicker], 1+s, RED);
         }
         uLCD.filled_circle(xPos[ticker], yPos[ticker], 3+s, RED);
         // save oldTicker spot
         oldTicker = ticker;
         // get new ticker position
         timer = 0;
         while (timer<100) {
             if (timer == 0) {
                 uLCD.filled_circle(xPos[ticker], yPos[ticker], 3+s, RED);
             } else if (timer == 70) {
                 uLCD.filled_circle(xPos[ticker], yPos[ticker], 3+s, LGREY);
             }
             if (myNav.fire()) {
                 uLCD.filled_circle(xPos[ticker], yPos[ticker], 3+s, GREEN);
                 switch(ticker) {
                     case 0:
                        rounds = 3;
                        break;
                     case 1:
                        rounds = 5;
                        break;
                     case 2:
                        rounds = 7;
                        break;
                     case 3:
                        playType = 0;
                        break;
                     case 4:
                        playType = 1;
                        break;
                     case 5:
                        main();
                  }
                  uLCD.color(BLUE);
                  uLCD.locate(4,7);
                  uLCD.printf("Rounds = %1d", rounds);
                  uLCD.color(DGREEN);
                  uLCD.locate(4,13);
                  uLCD.printf("Players = %1d", playType+1);
             } else if (myNav.up() || myNav.left()) {
                 wait(.2);
                 ticker = ticker - 1;
                 if (ticker < 0) {
                     ticker = sizeof(xPos)/4 - 1;
                 }
             } else if (myNav.down() || myNav.right()) {
                 wait(.2);
                 ticker = (ticker + 1) % (sizeof(xPos)/4);
             }
             wait(.01);
             timer++;
         }
     }
}

int main() {
     // read in highScoresArr from SD card
    
     FILE *fp = fopen("/sd/finalProj/highscores.txt", "r");
     if(fp == NULL) {
     uLCD.printf("Error Open \n");
     }
     for (int i=0; i<sizeof(highScoresArr)/4; i++) {
        fscanf(fp, "%4d", &highScoresArr[i]);
     }
     fclose(fp);
     // create menu interface
     uLCD.background_color(LBLUE);
     uLCD.cls();
     uLCD.filled_rectangle(0, 0, 200, 14, RED);
     uLCD.color(BLACK);
     uLCD.locate(1,0);
     uLCD.text_height(2);
     uLCD.text_width(2);
     uLCD.textbackground_color(RED);
     uLCD.printf("Screamer");
     uLCD.line(0, 14, 200, 14, RED);
     uLCD.line(0, 15, 200, 15, RED);
     uLCD.text_height(1);
     uLCD.text_width(1);
     uLCD.textbackground_color(LBLUE);
     uLCD.locate(7,4);
     uLCD.color(GREEN);
     uLCD.printf("PLAY");
     uLCD.locate(4,8);
     uLCD.color(ORANGE);
     uLCD.printf("HIGH SCORES");
     uLCD.locate(5,13);
     uLCD.color(LGREY);
     uLCD.printf("SETTINGS");
     uLCD.baudrate(BAUD_3000000); //jack up baud rate to max for fast display
     int xPos[3] = {40, 21, 28};
     int yPos[3] = {35, 67, 107};
     int ticker = 0;
     int oldTicker = 1;
     for (int i=0; i<sizeof(yPos)/4; i++) {
         uLCD.filled_circle(xPos[i], yPos[i], 2, RED);
     }
     nextsample.attach(&playMenuMusic, 1.0/8000.0);
     
     while (1) {
         // play music
         playMusic = 1;
         // Fill selector circle and if necessary, clear old
         if (oldTicker != ticker) {
            uLCD.filled_circle(xPos[oldTicker], yPos[oldTicker], 5+s, LBLUE);
            uLCD.filled_circle(xPos[oldTicker], yPos[oldTicker], 2+s, RED);
         }
         uLCD.filled_circle(xPos[ticker], yPos[ticker], 5+s, RED);
         // save oldTicker spot
         oldTicker = ticker;
         // get new ticker position
         timer = 0;
         while (timer<100) {
             if (timer == 0) {
                 uLCD.filled_circle(xPos[ticker], yPos[ticker], 5+s, RED);
             } else if (timer == 70) {
                 uLCD.filled_circle(xPos[ticker], yPos[ticker], 5+s, LBLUE);
             }
             if (myNav.fire()) {
                 uLCD.filled_circle(xPos[ticker], yPos[ticker], 3+s, GREEN);
                 wait(.1);
                 switch(ticker) {
                     case 0:
                        curTime = 0;
                        score1 = 0;
                        score2 = 0;
                        playMusic = 0;
                        play();
                        break;
                     case 1:
                        highScores();
                        break;
                     case 2:
                        settings();
                        break;
                 }
             } else if (myNav.up() || myNav.left()) {
                 wait(.2);
                 ticker = ticker - 1;
                 if (ticker < 0) {
                     ticker = sizeof(xPos)/4 - 1;
                 }
             } else if (myNav.down() || myNav.right()) {
                 wait(.2);
                 ticker = (ticker + 1) % (sizeof(xPos)/4);
             }
             wait(.01);
             timer++;
         }
     }
}