FRDM-KL25Z with Nokia 3110 type LCD display Using accelerometer to make movements
Dependencies: MMA8451Q N3310LCD mbed
Fork of FRDM_MMA8451Q by
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 }
Generated on Wed Jul 13 2022 01:12:45 by 1.7.2