A Stock Exchange Game using IO devices, the 128x128 uLCD, and other components

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

Fork of WavePlayer_HelloWorld by jim hamblen

Revision:
2:3585cd51c765
Parent:
1:5b8e223e983d
--- a/main.cpp	Thu Jan 24 02:59:05 2013 +0000
+++ b/main.cpp	Thu Nov 03 19:35:44 2016 +0000
@@ -1,8 +1,34 @@
-
 #include "mbed.h"
 #include "SDFileSystem.h"
 #include "wave_player.h"
+#include "ShiftBrite.h"
+#include "uLCD_4DGL.h"
+#include <mpr121.h>
 
+// Stock exchange game
+// Rohan Kumar Iyengar & Sai Sathiesh Rajan
+
+// Set up Mbed LEDs
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+DigitalOut led3(LED3);
+DigitalOut led4(LED4);
+
+// Create the interrupt receiver object on pin 26
+InterruptIn interrupt(p26);
+
+// Setup the i2c bus on pins 9 and 10
+I2C i2c(p9, p10);
+
+// Setup the Mpr121:
+// constructor(i2c object, i2c address of the mpr121)
+Mpr121 mpr121(&i2c, Mpr121::ADD_VSS);
+
+uLCD_4DGL uLCD(p28,p27,p30); // serial tx, serial rx, reset pin;
+
+SPI spi(p11, p12, p13);
+
+ShiftBrite myBrite(p15,p16,spi); //latch, enable, spi
 
 SDFileSystem sd(p5, p6, p7, p8, "sd"); //SD card
 
@@ -10,11 +36,287 @@
 
 wave_player waver(&DACout);
 
+int stockPrices [7] = {0,0,0,0,0,0,0}; // array to store trend data for current stock
+int maxEle = -1; // easily accessible max value of current trend data
+int minEle = 200; // easily accessible min value of current trend data
+int gameState = 0; // used to transition between game states
+int stocksChosen = 0; // number of stocks user has chosen already
+char* currentName; // current stock name
+char* chosenName1; // first chosen stock name
+char* chosenName2; // second chosen stock name
+int stockGain1 = 0; // first stock's profit/loss
+int stockGain2 = 0; // second stock's profit/loss
+int stockNamePos = 0; // Used to generate next stock name
+int stocksScrolled = 0; // Used to loop around stock names
+
+// Function to get next stock whenever user selects / rejects a stock
+void getNewStock()
+{
+    // Select stock name first
+    switch (stockNamePos) {
+    
+    case 0:
+        currentName = "Amazon";
+        break;
+    case 1:
+        currentName = "Google";
+        break;
+    case 2:
+        currentName = "Microsoft";
+        break;
+    case 3:
+        currentName = "Apple";
+        break;
+    case 4:
+        currentName = "IBM";
+        break;
+    case 5:
+        currentName = "Intel";
+        break;
+    case 6:
+        currentName = "Cisco";
+        break;
+    case 7:
+        currentName = "Mathworks";
+        break;
+    case 8:
+        currentName = "Uber";
+        break;
+    case 9:
+        currentName = "Facebook";
+        break;
+    }
+    
+    // Generate trend data for stock
+    srand(time(NULL));
+    float currentPrice = (rand() % 100) + 50; // initialize price
+    int trend = 0;
+    int range = 20;
+    int bound = 10;
+    stockPrices[0] = currentPrice;
+    maxEle = currentPrice;
+    minEle = currentPrice;
+    // Generate random data for first six days
+    for (int i = 1; i < 6; i++) {
+        float change = rand() % range - bound;
+        currentPrice = currentPrice + change;
+        stockPrices[i] = currentPrice;
+        if (currentPrice > maxEle) {
+            maxEle = currentPrice;
+        }
+        if (currentPrice < minEle) {
+            minEle = currentPrice;
+        }
+        int wildCard = rand() % 10 - 5;
+        if (change >= 0) {
+            trend++;
+            range = 15;
+            bound = 5 + wildCard;
+        } else {
+            trend--;
+            range = 15;
+            bound = 10 + wildCard;
+        }
+    }
+    
+    // Add more random data for 7th day
+    srand(time(NULL));
+    int finalWildCard = rand() % 8 - 4 + trend; 
+    float finalPrice = (1 + (finalWildCard / 34.0)) * currentPrice;
+    stockPrices[6] = finalPrice;
+    
+    // Increment counters to allow next stock retrieval to be smooth
+    stockNamePos = (stockNamePos + 1) % 10;
+    stocksScrolled++; 
+    if (stocksScrolled > 10 && stocksChosen != 2) {
+        stocksScrolled = 0;
+        stocksChosen = 0;
+        stockNamePos = rand() % 10;
+    }
+}
+
+// Uses current stock data to print a connected graph of points for that stock
+void printGraph() {
+    int x = 4;
+    // draw graph axes
+    uLCD.line(2, 20, 2, 126, LGREY);
+    uLCD.line(2, 126, 126, 126, LGREY);
+    float arrayRange = maxEle - minEle;
+    float graphRange = 110 - 30; 
+    float scaleFactor = graphRange / arrayRange;
+    int offset = 1;
+    for (int i = 0; i < 5; i++) {
+        int currDist = stockPrices[i] - minEle;
+        int y = (int) (110 - scaleFactor * currDist);
+        int nextDist = stockPrices[i + 1] - minEle;
+        int y2 = (int) (110 - scaleFactor * nextDist);
+        // Draw lines between each pair of points w/ color based on trend
+        if (y2 - y > 0) {
+            uLCD.line(x, y, x + 20, y2, RED);
+        } else if (y2 - y < 0) {
+            uLCD.line(x, y, x + 20, y2, GREEN);
+        } else {
+            uLCD.line(x, y, x + 20, y2, WHITE);
+        }
+        uLCD.filled_circle(x, y, 2, BLUE);
+        uLCD.filled_circle(x + 20, y2, 2, BLUE);
+        // Scale to row, col format of uLCD
+        int point1row = (int) ((x / 7.1) - .5);
+        int point1col = (int) ((y /8.0) - .5);
+        int point2col = (int) ((y2 / 8.0) - .5);
+        int point2row = (int) (((x + 20) / 7.1) - .5);
+        char buf1 [10];
+        char buf2 [10];
+        // NEED sprintf because printf on LCD has inexplicable behavior
+        sprintf(buf1, "%d", stockPrices[i]);
+        sprintf(buf2, "%d", stockPrices[i + 1]);
+        uLCD.text_string(buf1, point1row + 1, point1col + 1, FONT_12X16, WHITE);
+        offset*=-1;
+        //uLCD.locate(point2row + offset, point2col + offset);
+        //uLCD.printf("%3i", stockPrices[i+1]);
+        uLCD.text_string(buf2, point2row + 1, point2col + 1, FONT_12X16, WHITE);
+        x+=20;
+    }
+}
+
+// Interrupt when touch sensor is pressed
+void fallInterrupt() {
+    int key_code=0;
+    int i=0;
+    int value=mpr121.read(0x00);
+    value +=mpr121.read(0x01)<<8;
+    // LED demo mod code inspired by J. Hamblen
+    i=0;
+    // puts key number out to LEDs for demo
+    for (i=0; i<12; i++) {
+        if (((value>>i)&0x01)==1) key_code=i+1;
+        }
+    led4=key_code & 0x01;
+    led3=(key_code>>1) & 0x01;
+    led2=(key_code>>2) & 0x01;
+    led1=(key_code>>3) & 0x01;
+    if (key_code == 9 && stocksChosen < 2) {
+        gameState = 2;
+    }
+    if (key_code == 4 && stocksChosen < 2) {
+        gameState = 1;
+    }
+}
+
 int main()
 {
-    FILE *wave_file;
-    printf("\n\n\nHello, wave world!\n");
-    wave_file=fopen("/sd/sample.wav","r");
-    waver.play(wave_file);
-    fclose(wave_file);
+    myBrite.Write(1023, 1023 ,0);
+    bool finished = false;
+    // Do title sequence one time
+    // Welcome Sequence on Game Startup
+    uLCD.cls();
+    uLCD.text_string("Welcome to the\n Stock Exchange\n Challenge!" , 1, 1, FONT_12X16, GREEN);
+    wait(2);
+    uLCD.cls();
+    srand(time(NULL));
+    stockNamePos = rand() % 10;
+    // Title Screen Image
+    uLCD.media_init();
+    uLCD.set_sector_address(0x003A, 0x7C26);
+    uLCD.display_image(0,15); 
+    wait(3);
+    uLCD.cls();
+    uLCD.text_string("Look at stock \n trends then -" , 1, 1, FONT_12X16, BLUE);
+    uLCD.text_string("Pick two stocks \nthat will make\n you win BIG!", 1, 5, FONT_12X16, GREEN);
+    uLCD.text_string("Press button 8\n to choose the\n current stock", 1, 9, FONT_12X16, RED);
+    uLCD.text_string("Press button 3\n to move onto\n the next stock", 1, 13, FONT_12X16, WHITE);
+    wait(4);
+    uLCD.cls();
+    uLCD.text_string("Press 3 to begin!", 1, 7, FONT_12X16, GREEN);
+    // Now allow interrupts from touch sensor to trigger
+    interrupt.fall(&fallInterrupt);
+    interrupt.mode(PullUp);
+    
+    while (!finished) {
+        // State to move to next stock
+        if (gameState == 1) {
+            getNewStock();
+            uLCD.cls();
+            uLCD.text_string("Stock: ", 1, 1, FONT_12X16, GREEN);
+            uLCD.text_string(currentName, 7, 1, FONT_12X16, GREEN);
+            printGraph();
+            gameState = 0;
+        }
+        // State when stock is picked
+        if (gameState == 2) {
+            if (stocksChosen == 0) {
+                chosenName1 = currentName;
+                stockGain1 = stockPrices[6] - stockPrices[5];
+            } else {
+                chosenName2 = currentName;
+                stockGain2 = stockPrices[6] - stockPrices[5];
+            }
+            stocksChosen++;
+            if (stocksChosen > 1) {
+                finished = true;
+            } else {
+                gameState = 1;
+            }
+        }
+        wait(.5);
+    }
+    // End game summary + statistics
+    int totalGain = stockGain1 + stockGain2;
+    uLCD.cls();
+    if (totalGain <= 0) {
+        // Print losing image
+        myBrite.Write(1023 ,0,0);
+        uLCD.media_init();
+        uLCD.set_sector_address(0x003A, 0x7C01);
+        uLCD.display_image(0,22); 
+    } else {
+        myBrite.Write(0, 1023, 0);
+        // Print winning image
+        uLCD.media_init();
+        uLCD.set_sector_address(0x003A, 0x7C57);
+        uLCD.display_image(0,15); 
+    }
+    wait(1);
+    uLCD.cls();
+    // Print picks and statistics
+    uLCD.locate(0,0);
+    if (stockGain1 < 0) {
+        uLCD.color(RED);
+    } else if (stockGain1 > 0) {
+        uLCD.color(GREEN);
+    } else {
+        uLCD.color(WHITE);
+    }
+    uLCD.printf("Pick 1: %s\n\r", chosenName1);
+    uLCD.printf("Stock Gain 1: $%d\n\r\n", stockGain1);
+    if (stockGain2 < 0) {
+        uLCD.color(RED);
+    } else if (stockGain2 > 0) {
+        uLCD.color(GREEN);
+    } else {
+        uLCD.color(WHITE);
+    }
+    uLCD.printf("Pick 2: %s\n\r", chosenName2);
+    uLCD.printf("Stock Gain 2: $%d\n\r\n", stockGain2);
+    if (totalGain < 0) {
+        uLCD.color(RED);
+    } else if (totalGain > 0) {
+        uLCD.color(GREEN);
+    } else {
+        uLCD.color(WHITE);
+    }
+    uLCD.printf("\nTotal Gain: $%d\n\r", totalGain);
+    
+    // Play appropriate winning/losing sound
+    if (totalGain > 0) {
+        FILE* wave_file;
+        wave_file = fopen("/sd/Win.wav", "r");
+        waver.play(wave_file);
+        fclose(wave_file);
+    } else {
+        FILE* wave_file2;
+        wave_file2 = fopen("/sd/Lose.wav", "r");
+        waver.play(wave_file2);
+        fclose(wave_file2);
+    }
 }
\ No newline at end of file