Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: MMA8451Q N3310LCD mbed
Fork of FRDM_MMA8451Q by
main.cpp
- Committer:
 - SomeRandomBloke
 - Date:
 - 2013-03-21
 - Revision:
 - 10:f3e93cc092d7
 - Parent:
 - 9:1afbf9010118
 - Child:
 - 11:90d35ac294af
 
File content as of revision 10:f3e93cc092d7:
#include "mbed.h"
#include "MMA8451Q.h"
#include "N3310SPIConfig.h"
#include "N3310LCD.h"
#include "Joystick.h"
#include "splash.h"
#define MMA8451_I2C_ADDRESS (0x1d<<1)
Serial pc(USBTX,USBRX);
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
// menu starting points
#define MENU_X    10        // 0-83
#define MENU_Y    0        // 0-5
#define MENU_ITEMS 4
int8_t blflag = 1;  // Backlight initially ON
void about(N3310LCD* lcd, Joystick* jstick);
void draw(N3310LCD* lcd, Joystick* jstick);
void snakeGame(N3310LCD* lcd, Joystick* jstick);
void backlight(N3310LCD* lcd, Joystick* jstick);
void waitforOKKey(N3310LCD* lcd, Joystick* jstick);
uint8_t checkKeypressed( Joystick* jstick);
// menu definition
char menu_items[MENU_ITEMS][12] = {
    "SKETCH",
    "SNAKE",
    "BACKLIGHT",
    "ABOUT"
};
void (*menu_funcs[MENU_ITEMS])(N3310LCD*,Joystick*) = {
    draw,
    snakeGame,
    backlight,
    about
};
void about(N3310LCD* lcd, Joystick* jstick)
{
    lcd->writeString(0, 0,  "mbed-a-sketch", NORMAL);
    lcd->writeString(12, 1, "driven by", NORMAL);
    lcd->writeString(10, 2, "KL25Z mbed", NORMAL);
    lcd->writeString(0, 3,  "By AD Lindsay", NORMAL);
}
void backlight(N3310LCD* lcd, Joystick* jstick)
{
    lcd->writeString( 0, 1, "Toggle", NORMAL);
    lcd->writeString( 0, 2, "Backlight", NORMAL);
    if( blflag != 0 ) {
        lcd->writeString( 60, 2, "Off", HIGHLIGHT);
    } else {
        lcd->writeString( 60, 2, "On", HIGHLIGHT);
    }
    bool exitFlag = false;
    while( !exitFlag ) {
        for (int i = 0; i < NUM_KEYS; i++) {
            if (jstick->getKeyState(i) != 0) {
                jstick->resetKeyState(i);  // reset button flag
                switch(i) {
                    case CENTER_KEY:
                        exitFlag = true;
                        break;
                    case UP_KEY:
                    case DOWN_KEY:
                        if( blflag != 0 ) {
                            blflag=0;
                            lcd->backlight( OFF );
                        }   else {
                            blflag = 1;
                            lcd->backlight( ON );
                        }
                        lcd->writeString( 60, 2, (blflag != 0 ? (char*)"Off" : (char*)"On "), HIGHLIGHT);
                        break;
                }
            }
        }
    }
}
void draw(N3310LCD* lcd, Joystick* jstick)
{
    MMA8451Q acc(PTE25, PTE24, MMA8451_I2C_ADDRESS, false, 4);
    float x, y;
    float cValues[3] = { 0.0, 0.0, 0.0 };
    int16_t xI, yI;
    int16_t xInc, yInc;
    lcd->cls();
    // Take 100 readings to get stable centre point
    for( int i = 0; i < 100; i++ ) {
        float axis[3] = { 0.0, 0.0, 0.0 };
        acc.getAccAllAxis( axis );
        cValues[0] += axis[0];
        cValues[1] += axis[1];
    }
    cValues[0] /= 100.0;
    cValues[1] /= 100.0;
    // Draw a rectangle
    lcd->drawRectangle(0,0,83,47, PIXEL_ON);
    int8_t px = 42;
    int8_t py = 24;
    int8_t nx = px;
    int8_t ny = py;
    lcd->setPixel( px, py, PIXEL_ON );
    // Exit on joystick pressed
    bool exitFlag = false;
    while ( !exitFlag ) {
        uint8_t keyPress = checkKeypressed( jstick );
        if( keyPress == CENTER_KEY )
            exitFlag = true;
        x = (acc.getAccX() - cValues[0]) * 100.0;
        y = (acc.getAccY() - cValues[1]) * 100.0;
        xI = (int16_t)(x);
        yI = (int16_t)(y);
        xInc = xI/10;
        yInc = ((yI/10) * -1);
        nx += xInc;
        ny += yInc;
        nx = MAX( 1, MIN( nx, 82 ) );
        ny = MAX( 1, MIN( ny, 46 ) );
pc.printf( "X: %d Y: %d\n", nx, ny );
// Seem to have broken this
        if( abs(xInc) > 1 || abs(yInc) > 1 ) {
            // Draw line
            lcd->drawLine((uint8_t)px, (uint8_t)py, (uint8_t)nx, (uint8_t)ny, PIXEL_ON);
        } else {
            // Plot pixel
            lcd->setPixel( (uint8_t)nx, (uint8_t)ny, PIXEL_ON );
        }
        px = nx;
        py = ny;
        wait(0.1);
    }
}
#define MAX_SNAKE_LEN 400
#define SNAKE_X 0
#define SNAKE_Y 1
#define DIR_N 1
#define DIR_E 2
#define DIR_S 3
#define DIR_W 4
int16_t snakeLen = 10;
int8_t snake[MAX_SNAKE_LEN][2];       // Snake positions, use -1 for no point
void initSnake( void )
{
    for( int i=0; i< MAX_SNAKE_LEN; i++ ) {
        snake[i][SNAKE_X] = -1;
        snake[i][SNAKE_Y] = -1;
    }
    // Add initial snake points
    for(int i=0; i<snakeLen; i++ ) {
        snake[i][SNAKE_X] = 42 + i;
        snake[i][SNAKE_Y] = 24;
    }
}
void drawSnake( N3310LCD* lcd )
{
    for(int i=0; i<snakeLen; i++ ) {
        lcd->setPixel( snake[i][SNAKE_X], snake[i][SNAKE_Y], PIXEL_ON );
    }
}
void moveSnake( N3310LCD* lcd, uint8_t direction, uint8_t growLength )
{
    int8_t oX = snake[0][SNAKE_X];
    int8_t oY = snake[0][SNAKE_Y];
    switch( direction ) {
        case DIR_N:
            snake[0][SNAKE_Y]--;
            break;
        case DIR_E:
            snake[0][SNAKE_X]++;
            break;
        case DIR_S:
            snake[0][SNAKE_Y]++;
            break;
        case DIR_W:
            snake[0][SNAKE_X]--;
            break;
    }
    int8_t nX = -1;
    int8_t nY = -1;
    for(int i=1; i<snakeLen; i++ ) {
        nX = oX;
        nY = oY;
        oX = snake[i][SNAKE_X];
        oY = snake[i][SNAKE_Y];
        snake[i][SNAKE_X] = nX;
        snake[i][SNAKE_Y] = nY;        
    }
    drawSnake(lcd);
    if( growLength > 0 && snakeLen < MAX_SNAKE_LEN ) {
        // Dont clear tail, add point to tail
        snake[snakeLen][SNAKE_X] = oX;
        snake[snakeLen][SNAKE_Y] = oY;
        snakeLen++;
    } else {
        // Clear tail
        lcd->setPixel( oX, oY, PIXEL_OFF );
    }
    
}
bool checkCollision() {
bool collisionFlag = false;
    return collisionFlag;
}
void snakeGame(N3310LCD* lcd, Joystick* jstick)
{
    MMA8451Q acc(PTE25, PTE24, MMA8451_I2C_ADDRESS, false, 4);
    float x, y; //, z;
    float cValues[3] = { 0.0, 0.0, 0.0 };
    int16_t xI, yI; //, zI;
    int16_t xInc, yInc;
    // Take 100 readings to get stable centre point
    for( int i = 0; i < 100; i++ ) {
        float axis[3] = { 0.0, 0.0, 0.0 };
        acc.getAccAllAxis( axis );
        cValues[0] += axis[0];
        cValues[1] += axis[1];
//        cValues[2] += axis[2];
    }
    cValues[0] /= 100.0;
    cValues[1] /= 100.0;
//    cValues[2] /= 100.0;
//    pc.printf( "Steady State X: %f Y: %f Z: %f\n", cValues[0], cValues[1], cValues[2] );
    initSnake();
    lcd->cls();
    // Draw a rectangle
    lcd->drawRectangle(0,0,83,47, PIXEL_ON);
    drawSnake( lcd );
    for( int i=0; i<10; i++ ) {
        moveSnake(lcd, DIR_N, 1);
        wait(0.2);
    }
    for( int i=0; i<20; i++ ) {
        moveSnake(lcd, DIR_E, 0);
        wait(0.2);
    }
    for( int i=0; i<20; i++ ) {
        moveSnake(lcd, DIR_S, 1);
        wait(0.2);
    }
    for( int i=0; i<20; i++ ) {
        moveSnake(lcd, DIR_W, 1);
        wait(0.2);
    }
    int8_t px = 42;
    int8_t py = 25;
    int8_t nx = px;
    int8_t ny = py;
//    lcd->setPixel( px, py, PIXEL_ON );
    // Exit on joystick pressed
    bool exitFlag = false;
    uint8_t snakeDirection = DIR_W;
    uint8_t snakeGrowth = 0;
    
    while ( !exitFlag ) {
        uint8_t keyPress = checkKeypressed( jstick );
        if( keyPress == CENTER_KEY )
            exitFlag = true;
        x = (acc.getAccX() - cValues[0]) * 100.0;
        y = (acc.getAccY() - cValues[1]) * 100.0;
//        z = (acc.getAccZ() - cValues[2]) * 100.0;
//       pc.printf( "X: %f Y: %f Z: %f\n", x, y, z);
        xI = (int16_t)(x);
        yI = (int16_t)(y);
//        zI = (int16_t)(z);
        xInc = xI/10;
        yInc = ((yI/10) * -1);
        
        if( xInc > 2 )
            snakeDirection = DIR_E;
        else if( xInc < -2 )
            snakeDirection = DIR_W;
        else if( yInc > 2 )
            snakeDirection = DIR_S;
        else if( yInc < -2 )
            snakeDirection = DIR_N;
        moveSnake(lcd, snakeDirection, snakeGrowth);
        // TODO Check if we've collided with anything
        if( checkCollision() ) {
            // Collision detected!!
        }
        
        if( snakeGrowth > 0 ) snakeGrowth--;
        wait(0.2);
/*
        nx += xInc;
        ny += yInc;
        nx = MAX( 1, MIN( nx, 82 ) );
        ny = MAX( 1, MIN( ny, 46 ) );
        if( abs(xInc) > 1 || abs(yInc) > 1 ) {
            // Draw line
            lcd->drawLine((uint8_t)px, (uint8_t)py, (uint8_t)nx, (uint8_t)ny, PIXEL_ON);
        } else {
            // Plot pixel
            lcd->setPixel( (uint8_t)nx, (uint8_t)ny, PIXEL_ON );
        }
        px = nx;
        py = ny;
//        pc.printf( "X: %d Y: %d Z: %d\n", xI, yI, zI);
        wait(0.1);
        */
    }
}
void initMenu(N3310LCD* lcd)
{
    lcd->writeString(MENU_X, MENU_Y, menu_items[0], HIGHLIGHT );
    for (int i = 1; i < MENU_ITEMS; i++) {
        lcd->writeString(MENU_X, MENU_Y + i, menu_items[i], NORMAL);
    }
}
void waitforOKKey(N3310LCD* lcd, Joystick* jstick)
{
    lcd->writeString(38, 5, "OK", HIGHLIGHT );
    int key = 0xFF;
    while (key != CENTER_KEY) {
        for (int i = 0; i < NUM_KEYS; i++) {
            if (jstick->getKeyState(i) !=0) {
                jstick->resetKeyState(i);  // reset
                if (CENTER_KEY == i) key = CENTER_KEY;
            }
        }
    }
}
// Check if joystick is moved or pressed
uint8_t checkKeypressed( Joystick* jstick)
{
    uint8_t key = 0xFF;
    for(int i=0; i<NUM_KEYS; i++) {
        if (jstick->getKeyState(i) !=0) {
            jstick->resetKeyState(i);  // reset
            if (CENTER_KEY == i) key = CENTER_KEY;
        }
    }
    return key;
}
int main(void)
{
//    MMA8451Q acc(PTE25, PTE24, MMA8451_I2C_ADDRESS, false, 4);
    Joystick jstick(N3310SPIPort::AD0);
    N3310LCD lcd(N3310SPIPort::MOSI, N3310SPIPort::MISO, N3310SPIPort::SCK,
                 N3310SPIPort::CE, N3310SPIPort::DAT_CMD, N3310SPIPort::LCD_RST,
                 N3310SPIPort::BL_ON);
    lcd.init();
    lcd.cls();
    lcd.backlight(ON);
    // demo stuff
    // autoDemo(&lcd);
    lcd.drawBitmap(0, 0, splash, 84, 48);
    wait( 5 );
    lcd.cls();
    initMenu(&lcd);
    int currentMenuItem = 0;
    Ticker jstickPoll;
    jstickPoll.attach(&jstick, &Joystick::updateADCKey, 0.01);    // check ever 10ms
    while (true) {
        for (int i = 0; i < NUM_KEYS; i++) {
            if (jstick.getKeyState(i) != 0) {
                jstick.resetKeyState(i);  // reset button flag
                switch(i) {
                    case UP_KEY:
                        // current item to normal display
                        lcd.writeString(MENU_X, MENU_Y + currentMenuItem, menu_items[currentMenuItem], NORMAL);
                        currentMenuItem -=1;
                        if (currentMenuItem <0)  currentMenuItem = MENU_ITEMS -1;
                        // next item to highlight display
                        lcd.writeString(MENU_X, MENU_Y + currentMenuItem, menu_items[currentMenuItem], HIGHLIGHT);
                        break;
                    case DOWN_KEY:
                        // current item to normal display
                        lcd.writeString(MENU_X, MENU_Y + currentMenuItem, menu_items[currentMenuItem], NORMAL);
                        currentMenuItem +=1;
                        if(currentMenuItem >(MENU_ITEMS - 1))  currentMenuItem = 0;
                        // next item to highlight display
                        lcd.writeString(MENU_X, MENU_Y + currentMenuItem, menu_items[currentMenuItem], HIGHLIGHT);
                        break;
                    case LEFT_KEY:
                        initMenu(&lcd);
                        currentMenuItem = 0;
                        break;
                    case RIGHT_KEY:
                        lcd.cls();
                        (*menu_funcs[currentMenuItem])(&lcd, &jstick);
                        waitforOKKey(&lcd, &jstick);
                        lcd.cls();
                        initMenu(&lcd);
                        currentMenuItem = 0;
                        break;
                }
            }
        }
    }
    /*
    //    PwmOut rled(LED_RED);
    //    PwmOut gled(LED_GREEN);
    //    PwmOut bled(LED_BLUE);
        float x, y, z;
        float cValues[3] = { 0.0, 0.0, 0.0 };
        int16_t xI, yI, zI;
        // Take 100 readings to get stable centre point
        for( int i = 0; i < 100; i++ ) {
            float axis[3] = { 0.0, 0.0, 0.0 };
            acc.getAccAllAxis( axis );
            cValues[0] += axis[0];
            cValues[1] += axis[1];
            cValues[2] += axis[2];
        }
        cValues[0] /= 100.0;
        cValues[1] /= 100.0;
        cValues[2] /= 100.0;
        pc.printf( "Steady State X: %f Y: %f Z: %f\n", cValues[0], cValues[1], cValues[2] );
        while (true) {
            x = (acc.getAccX() - cValues[0]) * 100.0;
            y = (acc.getAccY() - cValues[1]) * 100.0;
            z = (acc.getAccZ() - cValues[2]) * 100.0;
     //       pc.printf( "X: %f Y: %f Z: %f\n", x, y, z);
            xI = (int16_t)(x);
            yI = (int16_t)(y);
            zI = (int16_t)(z);
            pc.printf( "X: %d Y: %d Z: %d\n", xI, yI, zI);
    //        pc.printf( "X: %f Y: %f Z: %f\n", x*100.0, y*100.0, z*100.0);
    //        rled = 1.0 - abs(acc.getAccX());
    //        gled = 1.0 - abs(acc.getAccY());
    //        bled = 1.0 - abs(acc.getAccZ());
            wait(0.5);
        }
    */
}
            
    