FRDM-KL25Z with Nokia 3110 type LCD display Using accelerometer to make movements
Dependencies: MMA8451Q N3310LCD mbed
Fork of FRDM_MMA8451Q by
main.cpp
- Committer:
- SomeRandomBloke
- Date:
- 2013-03-21
- Revision:
- 11:90d35ac294af
- Parent:
- 10:f3e93cc092d7
- Child:
- 12:dbd6c9c366ac
File content as of revision 11:90d35ac294af:
#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 centreBoard( MMA8451Q *acc, float *cValues ) { // 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] ); } 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; centreBoard( &acc, cValues ); 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 ); 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 MAX_FOOD 10 #define SNAKE_X 0 #define SNAKE_Y 1 #define DIR_N 1 #define DIR_E 2 #define DIR_S 3 #define DIR_W 4 #define FOOD_X 0 #define FOOD_Y 1 int16_t snakeLen = 10; int16_t foodCount = 0; int8_t snake[MAX_SNAKE_LEN][2]; // Snake positions, use -1 for no point int8_t food[MAX_FOOD][2]; 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( uint8_t dir) { bool collisionFlag = false; return collisionFlag; } void initFood() { for( uint8_t i = 0; i< MAX_FOOD; i++ ) { food[i][FOOD_X] = -1; food[i][FOOD_Y] = -1; } } // Get current snake head and work out if position is a food bool checkFood(uint8_t dir) { bool foodFlag = false; pc.printf("CHECK: X %d, Y %d\n",snake[0][SNAKE_X], snake[0][SNAKE_Y]); for( int i = 0; i < MAX_FOOD; i++ ) { pc.printf("FOOD: X %d, Y %d\n",food[i][FOOD_X], food[i][FOOD_Y]); if( snake[0][SNAKE_X] == food[i][FOOD_X] && snake[0][SNAKE_Y] == food[i][FOOD_Y] ) { foodFlag = true; food[i][FOOD_X] = -1; food[i][FOOD_Y] = -1; foodCount--; pc.printf("FOOD!\n"); break; } } return foodFlag; } bool isOnSnake( int8_t *sX, int8_t *sY ) { bool onSnake = false; pc.printf("isOnSnake sX = %d, sY = %d \n", *sX, *sY ); for( int i = 0; i< snakeLen; i++ ) { if( snake[i][SNAKE_X] == *sX && snake[i][SNAKE_Y] == *sY ) { onSnake = true; break; } } return onSnake; } void getRandomPosition( int8_t *rX, int8_t *rY ) { *rX = ((rand() % 100)*82)/100+1; *rY = ((rand() % 100)*46)/100+1; while( isOnSnake( rX, rY )) { *rX = ((rand() % 100)*82)/100+1; *rY = ((rand() % 100)*46)/100+1; } } void storeFood( int8_t fX, int8_t fY ) { pc.printf("Store fX = %d, fY = %d \n", fX, fY ); for( int i = 0; i< MAX_FOOD; i++ ) { if( food[i][FOOD_X] < 0 ) { pc.printf("Store in %d\n",i); food[i][FOOD_X] = fX; food[i][FOOD_Y] = fY; break; } } } void dropFood(N3310LCD* lcd) { // If no food present then drop some // Pick random x and y coords x >0 and x < 83, y > 0 and y <47 while( foodCount < MAX_FOOD ) { int8_t fX = 0; int8_t fY = 0; getRandomPosition( &fX, &fY ); lcd->setPixel( fX, fY, PIXEL_ON ); storeFood( fX, fY ); foodCount++; pc.printf("fX = %d, fY = %d \n", fX, fY ); } } 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; centreBoard( &acc, cValues ); lcd->cls(); // Draw a rectangle lcd->drawRectangle(0,0,83,47, PIXEL_ON); initSnake(); initFood(); dropFood(lcd); drawSnake( lcd ); /* Test to move snake 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; // pc.printf( "X: %f Y: %f Z: %f\n", x, y, z); xI = (int16_t)(x); yI = (int16_t)(y); 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; if( snakeGrowth > 0 ) snakeGrowth--; moveSnake(lcd, snakeDirection, snakeGrowth); // TODO Check if we've collided with anything if( checkCollision(snakeDirection) ) { // Collision detected!! } if( checkFood(snakeDirection) ) { // Gobbled some food!! // Indicate that snake is to grow during next moves snakeGrowth = 10; // Handle new food bing added to area dropFood(lcd); } // A little pause - vary this after snake length has reached 100, then 200, then 300 wait(0.2); } } 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); } */ }