The preloaded firmware shipped on the RETRO

Dependencies:   mbed

Revision:
2:6ab46f2e851a
Parent:
1:cd8a3926f263
--- a/Game.cpp	Mon Nov 17 19:51:24 2014 +0000
+++ b/Game.cpp	Fri Nov 21 20:13:10 2014 +0000
@@ -2,14 +2,93 @@
 
 const char* Game::LOSE_1 = "You lose.";
 const char* Game::LOSE_2 = "Press ship to restart.";
-const char* Game::SPLASH = "Press ship to start.";
+const char* Game::SPLASH_1 = "Press ship to start.";
+const char* Game::SPLASH_2 = "Press robot to switch.";
     
 Game::Game() : left(P0_14, PullUp), right(P0_11, PullUp), down(P0_12, PullUp), up(P0_13, PullUp), square(P0_16, PullUp), circle(P0_1, PullUp), led1(P0_9), led2(P0_8), pwm(P0_18), ain(P0_15), i2c(P0_5, P0_4) {
     srand(this->ain.read_u16());
     
+    this->lastUp = false;
+    this->lastDown = false;
+    this->mode = true;
+    
+    this->i2c.frequency(400);
+    this->writeRegister(0x2A, 0x01); 
+    
+    this->colors[0] = DisplayN18::RED;
+    this->colors[1] = DisplayN18::GREEN;
+    this->colors[2] = DisplayN18::BLUE;
+    
     this->initialize();
 }
 
+void Game::readRegisters(char address, char* buffer, int len) {
+    this->i2c.write(Game::I2C_ADDR, &address, 1, true);
+    this->i2c.read(Game::I2C_ADDR | 1, buffer, len);
+}
+
+int Game::writeRegister(char address, char value) {    
+    char buffer[2] = { address, value };
+    
+    return this->i2c.write(Game::I2C_ADDR, buffer, 2);
+}
+
+double Game::convert(char* buffer) {
+    double val = ((buffer[0] << 2) | (buffer[1] >> 6));
+            
+    if (val > 511.0) 
+        val -= 1024.0;
+    
+    return val / 512.0;
+}
+
+void Game::getXYZ(double& x, double& y, double& z) {
+    char buffer[6];
+    
+    this->readRegisters(0x01, buffer, 6);
+    
+    x = this->convert(buffer);
+    y = this->convert(buffer + 2);
+    z = this->convert(buffer + 4);
+}
+
+void Game::printDouble(double value, int x, int y) {
+    char buffer[10];
+    int len = sprintf(buffer, "%.1f", value);
+    
+    this->disp.drawString(x, y, buffer, DisplayN18::WHITE, DisplayN18::BLACK);
+}
+
+void Game::drawAxes() {
+    for (int i = 0; i < 3; i++) {
+        this->disp.drawLine(0, i * (Game::GRAPH_HEIGHT + Game::GRAPH_SPACING), 0, i * (Game::GRAPH_HEIGHT + Game::GRAPH_SPACING) + Game::GRAPH_HEIGHT, DisplayN18::WHITE);
+        this->disp.drawLine(0, i * (Game::GRAPH_HEIGHT + Game::GRAPH_SPACING) + Game::GRAPH_HEIGHT / 2, DisplayN18::WIDTH, i * (Game::GRAPH_HEIGHT + Game::GRAPH_SPACING) + Game::GRAPH_HEIGHT / 2, DisplayN18::WHITE);
+    }
+}
+
+void Game::drawPoint(int axis, double value) {
+    if (value < -1.0)
+        value = -1.0;
+
+    if (value > 1.0)
+        value = 1.0;
+
+    value += 1.0;
+    value /= 2.0;
+    value = 1.0 - value;
+    value *= Game::GRAPH_HEIGHT;
+
+    this->disp.setPixel(this->graphX, axis * (Game::GRAPH_HEIGHT + Game::GRAPH_SPACING) + (int)value, this->colors[axis]);
+}
+
+void Game::checkGraphReset() {
+    if (this->graphX > DisplayN18::WIDTH) {
+        this->graphX = 0;
+        this->disp.clear();
+        this->drawAxes();
+    }
+}
+
 void Game::initialize() {    
     this->initializeBall();
         
@@ -27,33 +106,88 @@
     this->ballX = DisplayN18::WIDTH / 2 - Game::BALL_RADIUS;
     this->ballY = DisplayN18::HEIGHT / 4 - Game::BALL_RADIUS;
     
-    this->ballSpeedX = rand() % (Game::MAX_BALL_SPEED * 2);
-    this->ballSpeedY = rand() % (Game::MAX_BALL_SPEED * 2);
+    this->ballSpeedX = rand() % 2 ? 1 : -1;
+    this->ballSpeedY = rand() % 2 ? 1 : -1;
+}
+
+void Game::tick() {  
+    this->checkButtons();
     
-    this->ballSpeedX -= Game::MAX_BALL_SPEED;
-    this->ballSpeedY -= Game::MAX_BALL_SPEED;
+    if (this->mode) {
+        this->clearPaddle();
+        this->clearBall();
+        
+        this->updatePaddle();
+        this->updateBall();
     
-    if (this->ballSpeedX == 0)
-        this->ballSpeedX++;
-    
-    if (this->ballSpeedY == 0)
-        this->ballSpeedY--;
+        this->checkCollision();
+        
+        this->drawPaddle();        
+        this->drawBall();
+        
+        this->checkPwm();
+        this->checkLives(); 
+        
+        wait_ms(25);
+    }
+    else {    
+        double x, y, z;
+        
+        this->getXYZ(x, y, z);
+        
+        this->checkGraphReset();
+        this->drawPoint(0, x);
+        this->drawPoint(1, y);
+        this->drawPoint(2, z);
+        this->graphX++;
+    } 
 }
 
-void Game::tick() {
-    this->clearPaddle();
-    this->clearBall();
+void Game::checkButtons() {
+    if (!this->square.read()) {
+        this->mode = !this->mode;
+        
+        this->disp.clear();
+        
+        if (!this->mode) {
+            this->graphX = 0;
+            
+            this->drawAxes();
+        }
+        
+        this->led1.write(this->mode);
+        this->led2.write(!this->mode);
+    }  
+    
+    bool xDir = this->ballSpeedX > 0;
+    bool yDir = this->ballSpeedY > 0;
+    bool isUp = !this->up.read();
+    bool isDown = !this->down.read();
     
-    this->updatePaddle();
-    this->updateBall();
-
-    this->checkCollision();
+    if (isUp && isDown) goto end;
+    if (!isUp && !isDown) goto end;
+    
+    if (isUp && this->lastUp) goto end;
+    if (isDown && this->lastDown) goto end;
+    
+    if (!xDir) this->ballSpeedX *= -1;
+    if (!yDir) this->ballSpeedY *= -1;
     
-    this->drawPaddle();        
-    this->drawBall();
+    if (isUp) {
+        if (++this->ballSpeedX > 5) this->ballSpeedX = 5;
+        if (++this->ballSpeedY > 5) this->ballSpeedY = 5;
+    }
+    else if (isDown) {
+        if (--this->ballSpeedX == 0) this->ballSpeedX = 1;
+        if (--this->ballSpeedY == 0) this->ballSpeedY = 1;
+    }
     
-    this->checkPwm();
-    this->checkLives();    
+    if (!xDir) this->ballSpeedX *= -1;
+    if (!yDir) this->ballSpeedY *= -1;
+    
+end:
+    this->lastUp = isUp;
+    this->lastDown = isDown;    
 }
 
 void Game::drawString(const char* str, int y) {
@@ -61,7 +195,8 @@
 }
 
 void Game::showSplashScreen() {
-    this->drawString(Game::SPLASH, DisplayN18::HEIGHT / 2 - DisplayN18::CHAR_HEIGHT / 2);  
+    this->drawString(Game::SPLASH_1, DisplayN18::HEIGHT / 2 - DisplayN18::CHAR_HEIGHT / 2);  
+    this->drawString(Game::SPLASH_2, DisplayN18::HEIGHT / 2 + DisplayN18::CHAR_HEIGHT / 2); 
        
     while (this->circle.read())
         wait_ms(1);