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