NXP Rapid IoT prototyping kit port of Silabs "hungry gecko" smake-like game. https://os.mbed.com/teams/SiliconLabs/code/Hungry_gecko/
Dependencies: lib_sx9500 GraphicsDisplay ColorMemLCD Large_fonts
See a detailed description of this project on Hackster.io . https://www.hackster.io/marcomerli/riotwear-snake-ca6dfc
main.cpp
- Committer:
- batman52
- Date:
- 2019-12-27
- Revision:
- 81:737dff75e013
- Parent:
- 80:77210aa1ad9c
File content as of revision 81:737dff75e013:
/***************************************************************************//** * @file main.cpp * @brief Demo program for game Hungry Gecko ******************************************************************************* * @section License * <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b> ******************************************************************************* * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. * * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no * obligation to support this Software. Silicon Labs is providing the * Software "AS IS", with no express or implied warranties of any kind, * including, but not limited to, any implied warranties of merchantability * or fitness for any particular purpose or warranties against infringement * of any proprietary rights of a third party. * * Silicon Labs will not be liable for any consequential, incidental, or * special damages, or any other relief, or for any claim by any third party, * arising from your use of this Software. * ******************************************************************************/ // #include "LS013B7DH03.h" #include "gecko.h" #include "food.h" #include "settings.h" // Rapid IoT LCD stuff #include "ColorMemLCD.h" #include "string" #include "Prototype24x27.h" #include "Prototype_num21x25.h" // #include "meirio_num11x14.h" #if(TOUCH_EN) #include "sx9500.h" #endif /**************************** Define I/O **************************************/ /* LEDS */ DigitalOut led_blue(LED_BLUE, 1); // 1 = OFF DigitalOut led_red(LED_RED, 1); DigitalOut led_green(PTE7,1); // 1 --> OFF, 0 --> ON /* Rapid IoT Buttons */ #if(!TOUCH_EN) // InterruptIn in(PTA4); InterruptIn in(PTE28); InterruptIn inB1(PTE9); // InterruptIn SW1(PTE8); // DigitalIn SW3(PTE10); // DigitalIn SW4(PTE28); #endif // !TOUCH_EN /* LCD */ DigitalOut lcd_light(PTE12, 1); // 1 = ON, 0 = OFF ColorMemLCD display( PTB22, PTB23, PTB21, PTB20, PTD15, PTD9, "TFT"); /* Touch sensor */ #if(TOUCH_EN) I2C i2c0(I2C_SDA , I2C_SCL ); // I2C_SCL = PTC10, I2C_SDA = PTC11, SX9500 touch(i2c0, PTA24, PTA9); // TOUCH_TXEN = PTA24, TOUCH_INT = PTA9 DigitalOut touch_rst(PTA2,1); // TOUCH_RST = PTA2 InterruptIn touch_int(PTA9); #endif /**************************** Define Timers ***********************************/ // LowPowerTicker ticker; Ticker ticker; /**************************** Global variables ********************************/ /* Flag that is set to true when the display is refreshed */ volatile bool refreshed = false; /* Flag that is set to true by the ticker. Makes the gecko move at regular time intervals */ volatile bool updateDisplay = true; /* A flag that ensures the controller to only read one click per frame */ volatile bool PBenabled = true; /* Direction in which the gecko moves */ Direction dir = UP; uint8_t score = 0; /**************************** Define callback handlers ************************/ void tickerCallback(void); /* Push button handlers */ void in_handler_B0(); void in_handler_B1(); /* Define game modes */ typedef enum { PLAY, STOP } Modes; /* Set the game mode */ Modes mode = PLAY; #if(TOUCH_EN) void in_handler_touch() { /* SX9500_TouchState_t ts; if (PBenabled) { ts = touch.read_proximity_sensors(); if(ts.downPressed && (dir != UP) ) dir = DOWN; if(ts.rightPressed && (dir != LEFT) ) dir = RIGHT; if(ts.upPressed && (dir != DOWN) ) dir = UP; if(ts.leftPressed && (dir != RIGHT) ) dir = LEFT; // if(!ts.downPressed && !ts.rightPressed && !ts.upPressed && !ts.leftPressed ) PBenabled = false; touch.service(); } */ led_green = !led_green; } void touch_service() { SX9500_TouchState_t ts; if (PBenabled) { ts = touch.read_proximity_sensors(); if(ts.downPressed && (dir != UP) ) dir = DOWN; if(ts.rightPressed && (dir != LEFT) ) dir = RIGHT; if(ts.upPressed && (dir != DOWN) ) dir = UP; if(ts.leftPressed && (dir != RIGHT) ) dir = LEFT; // if(!ts.downPressed && !ts.rightPressed && !ts.upPressed && !ts.leftPressed ) PBenabled = false; touch.service(); } // led_green = !led_green; } #else // TOUCH_EN void in_handler_B0() { /* Only change the direction if push button is enabled */ if (PBenabled) { switch (dir) { case (UP): dir = LEFT; break; case (DOWN): dir = RIGHT; break; case (RIGHT): dir = UP; break; case (LEFT): dir = DOWN; break; } PBenabled = false; } } void in_handler_B1() { /* Only change the direction if push button is enabled */ if (PBenabled) { switch (dir) { case UP: dir = RIGHT; break; case DOWN: dir = LEFT; break; case RIGHT: dir = DOWN; break; case LEFT: dir = UP; break; } PBenabled = false; } } #endif // TOUCH_EN /* Callback functions */ #define POLLING_LOOP 3 void pollingUpdate(void) { static uint8_t idx = POLLING_LOOP; idx--; if(idx==0) { display.polling(); idx = POLLING_LOOP; // led_blue = !led_blue; } } void tickerCallback(void) { updateDisplay = true; /* Enable push buttons if the display is refreshed */ PBenabled = refreshed; // led_red = !led_red; } void refreshCallback(void) { refreshed = true; } /**************************** Fill the boarder ********************************/ void fillEdge(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color) { #if(MULTI_UPDATE) display.window(x,y,w,h); #endif display.fill (x,y,w,h, color); #if(MULTI_UPDATE) display.update(); #endif } void fillBoarder(){ // fill score header fillEdge(0, 0, DISPLAY_WIDTH, TOPEDGE*STEPSIZE, FOREGROUND_COLOR); // Fill right edge fillEdge(DISPLAY_WIDTH - (BOARDERWIDTH/2), TOPEDGE*STEPSIZE + BOARDERWIDTH/2, 1, BOARD_HEIGHT*STEPSIZE, FOREGROUND_COLOR); for (uint8_t i=0;i<=BOARD_HEIGHT;i++){ for (uint8_t j=0;j<(DISPLAY_WIDTH-BOARD_WIDTH*STEPSIZE - BOARDERWIDTH/2);j++){ display.pixel(BOARD_WIDTH*STEPSIZE + BOARDERWIDTH/2 +j, (i+TOPEDGE)*STEPSIZE + BOARDERWIDTH/2+j, Black); } } // Fill bottom edge fillEdge(BOARDERWIDTH/2, (BOARD_HEIGHT+TOPEDGE)*STEPSIZE + BOARDERWIDTH/2, BOARD_WIDTH*STEPSIZE, 1, FOREGROUND_COLOR); for (uint8_t i=0;i<=BOARD_WIDTH;i++){ for (uint8_t j=0;j<(DISPLAY_WIDTH-BOARD_WIDTH*STEPSIZE - BOARDERWIDTH/2);j++){ display.pixel(i*STEPSIZE + BOARDERWIDTH/2 +j, (BOARD_HEIGHT+TOPEDGE)*STEPSIZE + BOARDERWIDTH/2+j, Black); } } // Fill left edge fillEdge(BOARDERWIDTH/2, TOPEDGE*STEPSIZE + BOARDERWIDTH/2, 1, BOARD_HEIGHT*STEPSIZE, Black); for (uint8_t i=0;i<=BOARD_HEIGHT;i++){ for (uint8_t j=0;j<(DISPLAY_WIDTH-BOARD_WIDTH*STEPSIZE - BOARDERWIDTH/2 - 1);j++){ // display.pixel(j, (i+TOPEDGE)*STEPSIZE + BOARDERWIDTH/2+j, Black); display.pixel(j, (i+TOPEDGE)*STEPSIZE + j, Black); } } // Fill top edge fillEdge(BOARDERWIDTH/2, TOPEDGE*STEPSIZE + BOARDERWIDTH/2 - 1, BOARD_WIDTH*STEPSIZE, 1, Black); for (uint8_t i=0;i<=BOARD_WIDTH;i++){ for (uint8_t j=0;j<(DISPLAY_WIDTH-BOARD_WIDTH*STEPSIZE - BOARDERWIDTH/2 - 1);j++){ // display.pixel(i*STEPSIZE + BOARDERWIDTH/2 + j, TOPEDGE*STEPSIZE + j, Black); display.pixel(i*STEPSIZE + j, TOPEDGE*STEPSIZE + j, Black); } } } void display_clear_all(void) { display.foreground(FOREGROUND_COLOR); display.background(BACKGROUND_COLOR); #if(MULTI_UPDATE) int j; int Divide = 8; // separate for 8 windows to save memory int Block = LCD_DISP_HEIGHT / Divide; for(j = 0 ; j <Divide ; j++) { display.window(0, j*Block, LCD_DISP_WIDTH, Block); display.cls(); display.update(); } #else display.window(0, 0, LCD_DISP_WIDTH, LCD_DISP_HEIGHT); display.cls(); display.update(); #endif } void display_score(void) { int j = 0; int Block = 27; // Text Font height; display.foreground(White); display.background(Black); #if(MULTI_UPDATE) display.window(0, j*Block, LCD_DISP_WIDTH, Block); #else display.window(0, 0, LCD_DISP_WIDTH, LCD_DISP_HEIGHT); #endif display.fill(0,0,LCD_DISP_WIDTH, Block, Black); display.locate(4, j*Block); display.printf("Score: %02d", score); #if(MULTI_UPDATE) display.update(); #else // reduce buffer window size to game area for faster refresh rate display.window(BOARDERWIDTH/2, TOPEDGE*STEPSIZE + BOARDERWIDTH/2, BOARD_WIDTH * STEPSIZE, BOARD_HEIGHT * STEPSIZE); #endif display.foreground(FOREGROUND_COLOR); display.background(BACKGROUND_COLOR); } #define GAME_OVER_X 40 void display_game_over(void) { int j = 3; int Block = 27; // Text Font height: 6 lines of text display.window(0, j*Block, LCD_DISP_WIDTH, Block); display.locate(GAME_OVER_X, j*Block); display.printf("GAME"); display.update(); j++; display.window(0, j*Block, LCD_DISP_WIDTH, Block); display.locate(GAME_OVER_X, j*Block); display.printf("OVER!"); display.update(); } /**************************** MAIN ********************************************/ int main() { #if(TOUCH_EN) wait(1); touch.reset(); wait(0.3); // wait until the reset has finished touch.init(); wait(0.3); touch.set_active(true); wait(0.3); touch_int.fall(in_handler_touch); #else // TOUCH_EN /* Initialize pushbutton handlers */ in.fall(in_handler_B0); inB1.fall(in_handler_B1); #endif // TOUCH_EN /* Enable the LCD */ display.command_AllClear(); display.set_font( (unsigned char*)Prototype24x27 ); #if TICKER_EN /* Start generating the 3Hz call */ ticker.attach(&tickerCallback, 0.3333f); #endif /* Reset the LCD to a blank state. (All white) */ display_clear_all(); fillBoarder(); display_score(); Gecko gck; Food fd; gck.draw(display); fd.draw(display); /* Push update to the display */ display.update(); /* Main loop */ while (1) { #if(TICKER_EN) sleep(); #else wait(0.2); #endif // update button status refreshCallback(); #if(!TICKER_EN) tickerCallback(); #endif #if(TOUCH_EN) touch_service(); #endif if (updateDisplay && refreshed && (mode==PLAY)) { updateDisplay = false; refreshed = false; pollingUpdate(); gck.move(display, dir); if (fd.isEaten(gck)) { fd.reset(display, gck); gck.increaseLength(display, dir); /* Redraw gecko */ gck.draw(display); /* Update the score */ score++; display_score(); } if (gck.selfCollision()) { mode = STOP; gck.move(display, dir); display_game_over(); } /* Update display */ refreshed = false; display.update(); } } }