FRDM-KL25Z with Nokia 3110 type LCD display Using accelerometer to make movements

Dependencies:   MMA8451Q N3310LCD mbed

Fork of FRDM_MMA8451Q by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "MMA8451Q.h"
00003 #include "N3310SPIConfig.h"
00004 #include "N3310LCD.h"
00005 #include "Joystick.h"
00006 #include "splash.h"
00007 
00008 #define MMA8451_I2C_ADDRESS (0x1d<<1)
00009 Serial pc(USBTX,USBRX);
00010 
00011 #define MIN(a,b) (((a)<(b))?(a):(b))
00012 #define MAX(a,b) (((a)>(b))?(a):(b))
00013 
00014 // menu starting points
00015 #define MENU_X    10        // 0-83
00016 #define MENU_Y    1        // 0-5
00017 
00018 #define MENU_ITEMS 4
00019 
00020 int8_t blflag = 1;  // Backlight initially ON
00021 
00022 void about(N3310LCD* lcd, Joystick* jstick);
00023 void draw(N3310LCD* lcd, Joystick* jstick);
00024 void snakeGame(N3310LCD* lcd, Joystick* jstick);
00025 void setup(N3310LCD* lcd, Joystick* jstick);
00026 void waitforOKKey(N3310LCD* lcd, Joystick* jstick);
00027 uint8_t checkKeypressed( Joystick* jstick);
00028 
00029 // menu definition
00030 char menu_items[MENU_ITEMS][12] = {
00031     "SKETCH",
00032     "SNAKE",
00033     "SETUP",
00034     "ABOUT"
00035 };
00036 
00037 void (*menu_funcs[MENU_ITEMS])(N3310LCD*,Joystick*) = {
00038     draw,
00039     snakeGame,
00040     setup,
00041     about
00042 };
00043 
00044 
00045 void about(N3310LCD* lcd, Joystick* jstick)
00046 {
00047     lcd->writeString(6, 0,  "mbed and LCD", NORMAL);
00048     lcd->writeString(0, 1, "demos on KL25Z", NORMAL);
00049     lcd->writeString(36, 2, "By", NORMAL);
00050     lcd->writeString(0, 3,  "Andrew Lindsay", NORMAL);
00051 }
00052 
00053 void setup(N3310LCD* lcd, Joystick* jstick)
00054 {
00055     lcd->writeString( 0, 1, "Toggle", NORMAL);
00056     lcd->writeString( 0, 2, "Backlight", NORMAL);
00057     if( blflag != 0 ) {
00058         lcd->writeString( 60, 2, "Off", HIGHLIGHT);
00059     } else {
00060         lcd->writeString( 60, 2, "On", HIGHLIGHT);
00061     }
00062 
00063     bool exitFlag = false;
00064 
00065     while( !exitFlag ) {
00066         for (int i = 0; i < NUM_KEYS; i++) {
00067             if (jstick->getKeyState(i) != 0) {
00068                 jstick->resetKeyState(i);  // reset button flag
00069                 switch(i) {
00070                     case CENTER_KEY:
00071                         exitFlag = true;
00072                         break;
00073                     case UP_KEY:
00074                     case DOWN_KEY:
00075                         if( blflag != 0 ) {
00076                             blflag=0;
00077                             lcd->backlight( OFF );
00078                         }   else {
00079                             blflag = 1;
00080                             lcd->backlight( ON );
00081                         }
00082                         lcd->writeString( 60, 2, (blflag != 0 ? (char*)"Off" : (char*)"On "), HIGHLIGHT);
00083                         break;
00084                 }
00085             }
00086         }
00087     }
00088 }
00089 
00090 void centreBoard( MMA8451Q *acc, float *cValues )
00091 {
00092     // Take 100 readings to get stable centre point
00093     for( int i = 0; i < 100; i++ ) {
00094         float axis[3] = { 0.0, 0.0, 0.0 };
00095         acc->getAccAllAxis( axis );
00096         cValues[0] += axis[0];
00097         cValues[1] += axis[1];
00098         cValues[2] += axis[2];
00099     }
00100     cValues[0] /= 100.0;
00101     cValues[1] /= 100.0;
00102     cValues[2] /= 100.0;
00103 //    pc.printf( "Steady State X: %f Y: %f Z: %f\n", cValues[0], cValues[1], cValues[2] );
00104 }
00105 
00106 
00107 void draw(N3310LCD* lcd, Joystick* jstick)
00108 {
00109     MMA8451Q acc(PTE25, PTE24, MMA8451_I2C_ADDRESS, false, 4);
00110     float x, y;
00111     float cValues[3] = { 0.0, 0.0, 0.0 };
00112     int16_t xI, yI;
00113     int16_t xInc, yInc;
00114     int8_t px = 42;
00115     int8_t py = 24;
00116     int8_t nx = px;
00117     int8_t ny = py;
00118 
00119     lcd->drawBitmap(0, 0, splashSketch, 84, 48);
00120     wait( 5 );
00121 
00122     centreBoard( &acc, cValues );
00123     lcd->cls();
00124 
00125     // Draw a rectangle
00126     lcd->drawRectangle(0,0,83,47, PIXEL_ON);
00127     lcd->setPixel( px, py, PIXEL_ON );
00128 
00129     // Exit on joystick pressed
00130     bool exitFlag = false;
00131     while ( !exitFlag ) {
00132         uint8_t keyPress = checkKeypressed( jstick );
00133         if( keyPress == CENTER_KEY )
00134             exitFlag = true;
00135 
00136         x = (acc.getAccX() - cValues[0]) * 100.0;
00137         y = (acc.getAccY() - cValues[1]) * 100.0;
00138 
00139         xI = (int16_t)(x);
00140         yI = (int16_t)(y);
00141         xInc = xI/10;
00142         yInc = ((yI/10) * -1);
00143 
00144         nx += xInc;
00145         ny += yInc;
00146 
00147         nx = MAX( 1, MIN( nx, 82 ) );
00148         ny = MAX( 1, MIN( ny, 46 ) );
00149 //pc.printf( "X: %d Y: %d\n", nx, ny );
00150 
00151         if( abs(xInc) > 1 || abs(yInc) > 1 ) {
00152             // Draw line
00153             lcd->drawLine((uint8_t)px, (uint8_t)py, (uint8_t)nx, (uint8_t)ny, PIXEL_ON);
00154         } else {
00155             // Plot pixel
00156             lcd->setPixel( (uint8_t)nx, (uint8_t)ny, PIXEL_ON );
00157         }
00158 
00159         px = nx;
00160         py = ny;
00161 
00162         wait(0.1);
00163     }
00164 }
00165 
00166 #define MAX_SNAKE_LEN 400
00167 #define MAX_FOOD 5
00168 #define SNAKE_X 0
00169 #define SNAKE_Y 1
00170 #define DIR_N 1
00171 #define DIR_E 2
00172 #define DIR_S 3
00173 #define DIR_W 4
00174 #define FOOD_X 0
00175 #define FOOD_Y 1
00176 
00177 int16_t snakeLen = 10;
00178 int16_t foodCount = 0;
00179 
00180 int8_t snake[MAX_SNAKE_LEN][2];       // Snake positions, use -1 for no point
00181 int8_t food[MAX_FOOD][2];
00182 
00183 void initSnake( void )
00184 {
00185     snakeLen = 10;
00186     for( int i=0; i< MAX_SNAKE_LEN; i++ ) {
00187         snake[i][SNAKE_X] = -1;
00188         snake[i][SNAKE_Y] = -1;
00189     }
00190 
00191     // Add initial snake points
00192     for(int i=0; i<snakeLen; i++ ) {
00193         snake[i][SNAKE_X] = 42 + i;
00194         snake[i][SNAKE_Y] = 24;
00195     }
00196 }
00197 
00198 void drawSnake( N3310LCD* lcd )
00199 {
00200     for(int i=0; i<snakeLen; i++ ) {
00201         lcd->setPixel( snake[i][SNAKE_X], snake[i][SNAKE_Y], PIXEL_ON );
00202     }
00203 }
00204 
00205 
00206 void moveSnake( N3310LCD* lcd, uint8_t direction, uint8_t growLength )
00207 {
00208     int8_t oX = snake[0][SNAKE_X];
00209     int8_t oY = snake[0][SNAKE_Y];
00210     switch( direction ) {
00211         case DIR_N:
00212             snake[0][SNAKE_Y]--;
00213             break;
00214         case DIR_E:
00215             snake[0][SNAKE_X]++;
00216             break;
00217         case DIR_S:
00218             snake[0][SNAKE_Y]++;
00219             break;
00220         case DIR_W:
00221             snake[0][SNAKE_X]--;
00222             break;
00223     }
00224 
00225     int8_t nX = -1;
00226     int8_t nY = -1;
00227     for(int i=1; i<snakeLen; i++ ) {
00228         nX = oX;
00229         nY = oY;
00230         oX = snake[i][SNAKE_X];
00231         oY = snake[i][SNAKE_Y];
00232         snake[i][SNAKE_X] = nX;
00233         snake[i][SNAKE_Y] = nY;
00234     }
00235 
00236     // Plot head at new position as this is only part that is moving
00237     lcd->setPixel( snake[0][SNAKE_X], snake[0][SNAKE_Y], PIXEL_ON );
00238     
00239     if( growLength > 0 && snakeLen < MAX_SNAKE_LEN ) {
00240         // Dont clear tail, add point to tail
00241         snake[snakeLen][SNAKE_X] = oX;
00242         snake[snakeLen][SNAKE_Y] = oY;
00243         snakeLen++;
00244     } else {
00245         // Clear tail
00246         lcd->setPixel( oX, oY, PIXEL_OFF );
00247     }
00248 }
00249 
00250 bool isOnSnake( int8_t sX, int8_t sY )
00251 {
00252     bool onSnake = false;
00253 //    pc.printf("isOnSnake sX = %d, sY = %d \n", *sX, *sY );
00254     for( int i = 0; i< snakeLen; i++ ) {
00255         if( snake[i][SNAKE_X] == sX && snake[i][SNAKE_Y] == sY ) {
00256             onSnake = true;
00257             break;
00258         }
00259     }
00260     return onSnake;
00261 }
00262 
00263 bool checkCollision( uint8_t dir)
00264 {
00265     bool collisionFlag = false;
00266     int8_t nX = snake[0][SNAKE_X];
00267     int8_t nY = snake[0][SNAKE_Y];
00268     
00269     switch( dir) {
00270         case DIR_N:
00271             nY--;
00272             break;
00273         case DIR_E:
00274             nX++;
00275             break;
00276         case DIR_S:
00277             nY++;
00278             break;
00279         case DIR_W:
00280             nX--;
00281             break;    
00282     }
00283     if( isOnSnake( nX, nY ) )
00284         return true;
00285 
00286     if( snake[0][SNAKE_X] <= 0 || snake[0][SNAKE_X] >= 83 || 
00287         snake[0][SNAKE_Y] <= 0 || snake[0][SNAKE_Y] >= 47 )
00288         return true;
00289         
00290     return collisionFlag;
00291 }
00292 
00293 
00294 void initFood()
00295 {
00296     foodCount = 0;
00297     for( uint8_t i = 0; i< MAX_FOOD; i++ ) {
00298         food[i][FOOD_X] = -1;
00299         food[i][FOOD_Y] = -1;
00300     }
00301 }
00302 
00303 
00304 // Get current snake head and work out if position is a food
00305 bool checkFood(uint8_t dir)
00306 {
00307     bool foodFlag = false;
00308     for( int i = 0; i < MAX_FOOD; i++ ) {
00309         if( snake[0][SNAKE_X] == food[i][FOOD_X] && snake[0][SNAKE_Y] == food[i][FOOD_Y] ) {
00310             foodFlag = true;
00311             food[i][FOOD_X] = -1;
00312             food[i][FOOD_Y] = -1;
00313             foodCount--;
00314             break;
00315         }
00316     }
00317     return foodFlag;
00318 }
00319 
00320 
00321 void getRandomPosition( int8_t *rX, int8_t *rY )
00322 {
00323     *rX = ((rand() % 100)*82)/100+1;
00324     *rY = ((rand() % 100)*46)/100+1;
00325 
00326     while( isOnSnake( *rX, *rY )) {
00327         *rX = ((rand() % 100)*82)/100+1;
00328         *rY = ((rand() % 100)*46)/100+1;
00329     }
00330 
00331 }
00332 
00333 void storeFood( int8_t fX, int8_t fY )
00334 {
00335     for( int i = 0; i< MAX_FOOD; i++ ) {
00336         if( food[i][FOOD_X] < 0 ) {
00337             food[i][FOOD_X] = fX;
00338             food[i][FOOD_Y] = fY;
00339             break;
00340         }
00341     }
00342 }
00343 
00344 
00345 void dropFood(N3310LCD* lcd)
00346 {
00347     // If no food present then drop some
00348     // Pick random x and y coords x >0 and x < 83, y > 0 and y <47
00349     while( foodCount < MAX_FOOD ) {
00350         int8_t fX = 0;
00351         int8_t fY = 0;
00352         getRandomPosition( &fX, &fY );
00353         lcd->setPixel( fX, fY, PIXEL_ON );
00354         storeFood( fX, fY );
00355         foodCount++;
00356     }
00357 }
00358 
00359 void snakeGame(N3310LCD* lcd, Joystick* jstick)
00360 {
00361     MMA8451Q acc(PTE25, PTE24, MMA8451_I2C_ADDRESS, false, 4);
00362     float x, y; //, z;
00363     float cValues[3] = { 0.0, 0.0, 0.0 };
00364     int16_t xI, yI; //, zI;
00365     int16_t xInc, yInc;
00366 
00367     lcd->drawBitmap(0, 0, splashSnake, 84, 48);
00368     wait( 3 );
00369     
00370     centreBoard( &acc, cValues );
00371 
00372     lcd->cls();
00373 
00374     // Draw a rectangle
00375     lcd->drawRectangle(0,0,83,47, PIXEL_ON);
00376 
00377     initSnake();
00378     initFood();
00379     dropFood(lcd);
00380     drawSnake( lcd );
00381     /* Test to move snake
00382         for( int i=0; i<10; i++ ) {
00383             moveSnake(lcd, DIR_N, 1);
00384             wait(0.2);
00385         }
00386         for( int i=0; i<20; i++ ) {
00387             moveSnake(lcd, DIR_E, 0);
00388             wait(0.2);
00389         }
00390         for( int i=0; i<20; i++ ) {
00391             moveSnake(lcd, DIR_S, 1);
00392             wait(0.2);
00393         }
00394         for( int i=0; i<20; i++ ) {
00395             moveSnake(lcd, DIR_W, 1);
00396             wait(0.2);
00397         }
00398     */
00399 
00400     // Exit on joystick pressed
00401     bool exitFlag = false;
00402     uint8_t snakeDirection = DIR_W;
00403     uint8_t snakeGrowth = 0;
00404 
00405     while ( !exitFlag ) {
00406         uint8_t keyPress = checkKeypressed( jstick );
00407         if( keyPress == CENTER_KEY )
00408             exitFlag = true;
00409 
00410         x = (acc.getAccX() - cValues[0]) * 100.0;
00411         y = (acc.getAccY() - cValues[1]) * 100.0;
00412 //       pc.printf( "X: %f Y: %f Z: %f\n", x, y, z);
00413 
00414         xI = (int16_t)(x);
00415         yI = (int16_t)(y);
00416         xInc = xI/10;
00417         yInc = ((yI/10) * -1);
00418 
00419         if( xInc > 2 )
00420             snakeDirection = DIR_E;
00421         else if( xInc < -2 )
00422             snakeDirection = DIR_W;
00423         else if( yInc > 2 )
00424             snakeDirection = DIR_S;
00425         else if( yInc < -2 )
00426             snakeDirection = DIR_N;
00427 
00428         if( snakeGrowth > 0 ) snakeGrowth--;
00429 
00430         moveSnake(lcd, snakeDirection, snakeGrowth);
00431         // TODO Check if we've collided with anything
00432         if( checkCollision(snakeDirection) ) {
00433             // Collision detected!!
00434             lcd->writeString(30, 2, "GAME", NORMAL);
00435             lcd->writeString(30, 3, "OVER", NORMAL);
00436             exitFlag = true;
00437             continue;
00438         }
00439 
00440         if( checkFood(snakeDirection) ) {
00441             // Gobbled some food!!
00442             // Indicate that snake is to grow during next moves
00443             snakeGrowth = 10;
00444 
00445             // Drop more food into area
00446             dropFood(lcd);
00447         }
00448 
00449         // A little pause - vary this after snake length has reached 100, then 200, then 300
00450         wait(0.2);
00451 
00452     }
00453 
00454 }
00455 
00456 
00457 
00458 void initMenu(N3310LCD* lcd)
00459 {
00460     lcd->writeString(MENU_X, MENU_Y, menu_items[0], HIGHLIGHT );
00461 
00462     for (int i = 1; i < MENU_ITEMS; i++) {
00463         lcd->writeString(MENU_X, MENU_Y + i, menu_items[i], NORMAL);
00464     }
00465 }
00466 
00467 void waitforOKKey(N3310LCD* lcd, Joystick* jstick)
00468 {
00469     lcd->writeString(38, 5, "OK", HIGHLIGHT );
00470 
00471     int key = 0xFF;
00472     while (key != CENTER_KEY) {
00473         for (int i = 0; i < NUM_KEYS; i++) {
00474             if (jstick->getKeyState(i) !=0) {
00475                 jstick->resetKeyState(i);  // reset
00476                 if (CENTER_KEY == i) key = CENTER_KEY;
00477             }
00478         }
00479     }
00480 }
00481 
00482 // Check if joystick is moved or pressed
00483 uint8_t checkKeypressed( Joystick* jstick)
00484 {
00485     uint8_t key = 0xFF;
00486 
00487     for(int i=0; i<NUM_KEYS; i++) {
00488         if (jstick->getKeyState(i) !=0) {
00489             jstick->resetKeyState(i);  // reset
00490             if (CENTER_KEY == i) key = CENTER_KEY;
00491         }
00492     }
00493     return key;
00494 }
00495 
00496 
00497 int main(void)
00498 {
00499 //    MMA8451Q acc(PTE25, PTE24, MMA8451_I2C_ADDRESS, false, 4);
00500     Joystick jstick(N3310SPIPort::AD0);
00501     N3310LCD lcd(N3310SPIPort::MOSI, N3310SPIPort::MISO, N3310SPIPort::SCK,
00502                  N3310SPIPort::CE, N3310SPIPort::DAT_CMD, N3310SPIPort::LCD_RST,
00503                  N3310SPIPort::BL_ON);
00504     lcd.init();
00505     lcd.cls();
00506     lcd.backlight(ON);
00507 
00508     // demo stuff
00509     // autoDemo(&lcd);
00510 
00511     lcd.drawBitmap(0, 0, splashMain, 84, 48);
00512     wait( 3 );
00513     lcd.cls();
00514 
00515     initMenu(&lcd);
00516     int currentMenuItem = 0;
00517     Ticker jstickPoll;
00518     jstickPoll.attach(&jstick, &Joystick::updateADCKey, 0.01);    // check ever 10ms
00519 
00520     while (true) {
00521         for (int i = 0; i < NUM_KEYS; i++) {
00522             if (jstick.getKeyState(i) != 0) {
00523                 jstick.resetKeyState(i);  // reset button flag
00524                 switch(i) {
00525                     case UP_KEY:
00526                         // current item to normal display
00527                         lcd.writeString(MENU_X, MENU_Y + currentMenuItem, menu_items[currentMenuItem], NORMAL);
00528                         currentMenuItem -=1;
00529                         if (currentMenuItem <0)  currentMenuItem = MENU_ITEMS -1;
00530                         // next item to highlight display
00531                         lcd.writeString(MENU_X, MENU_Y + currentMenuItem, menu_items[currentMenuItem], HIGHLIGHT);
00532                         break;
00533 
00534                     case DOWN_KEY:
00535                         // current item to normal display
00536                         lcd.writeString(MENU_X, MENU_Y + currentMenuItem, menu_items[currentMenuItem], NORMAL);
00537                         currentMenuItem +=1;
00538                         if(currentMenuItem >(MENU_ITEMS - 1))  currentMenuItem = 0;
00539                         // next item to highlight display
00540                         lcd.writeString(MENU_X, MENU_Y + currentMenuItem, menu_items[currentMenuItem], HIGHLIGHT);
00541                         break;
00542 
00543                     case LEFT_KEY:
00544                         initMenu(&lcd);
00545                         currentMenuItem = 0;
00546                         break;
00547 
00548                     case RIGHT_KEY:
00549                         lcd.cls();
00550                         (*menu_funcs[currentMenuItem])(&lcd, &jstick);
00551                         waitforOKKey(&lcd, &jstick);
00552                         lcd.cls();
00553                         initMenu(&lcd);
00554                         currentMenuItem = 0;
00555                         break;
00556                 }
00557             }
00558         }
00559     }
00560 
00561     /*
00562     //    PwmOut rled(LED_RED);
00563     //    PwmOut gled(LED_GREEN);
00564     //    PwmOut bled(LED_BLUE);
00565         float x, y, z;
00566         float cValues[3] = { 0.0, 0.0, 0.0 };
00567         int16_t xI, yI, zI;
00568 
00569         // Take 100 readings to get stable centre point
00570 
00571         for( int i = 0; i < 100; i++ ) {
00572             float axis[3] = { 0.0, 0.0, 0.0 };
00573             acc.getAccAllAxis( axis );
00574             cValues[0] += axis[0];
00575             cValues[1] += axis[1];
00576             cValues[2] += axis[2];
00577         }
00578 
00579         cValues[0] /= 100.0;
00580         cValues[1] /= 100.0;
00581         cValues[2] /= 100.0;
00582         pc.printf( "Steady State X: %f Y: %f Z: %f\n", cValues[0], cValues[1], cValues[2] );
00583 
00584         while (true) {
00585 
00586             x = (acc.getAccX() - cValues[0]) * 100.0;
00587             y = (acc.getAccY() - cValues[1]) * 100.0;
00588             z = (acc.getAccZ() - cValues[2]) * 100.0;
00589      //       pc.printf( "X: %f Y: %f Z: %f\n", x, y, z);
00590 
00591             xI = (int16_t)(x);
00592             yI = (int16_t)(y);
00593             zI = (int16_t)(z);
00594             pc.printf( "X: %d Y: %d Z: %d\n", xI, yI, zI);
00595     //        pc.printf( "X: %f Y: %f Z: %f\n", x*100.0, y*100.0, z*100.0);
00596     //        rled = 1.0 - abs(acc.getAccX());
00597     //        gled = 1.0 - abs(acc.getAccY());
00598     //        bled = 1.0 - abs(acc.getAccZ());
00599             wait(0.5);
00600         }
00601     */
00602 }