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
main.cpp
- Committer:
- RohanIyengar
- Date:
- 2016-11-03
- Revision:
- 2:3585cd51c765
- Parent:
- 1:5b8e223e983d
File content as of revision 2:3585cd51c765:
#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
AnalogOut DACout(p18);
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()
{
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);
}
}
