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
Diff: main.cpp
- Revision:
- 80:77210aa1ad9c
- Parent:
- 79:0431b9fd3dc0
- Child:
- 81:737dff75e013
diff -r 0431b9fd3dc0 -r 77210aa1ad9c main.cpp --- a/main.cpp Sat Nov 23 18:03:20 2019 +0000 +++ b/main.cpp Thu Dec 26 16:47:58 2019 +0000 @@ -1,32 +1,375 @@ -#include "mbed.h" - -DigitalOut rgb_red(LED_RED, 1); // LED1 = LED_RED, 1 --> OFF, 0 --> ON -DigitalOut rgb_blue(LED_BLUE, 1); // LED3 = LED_BLUE, 1 --> OFF, 0 --> ON -DigitalOut rgb_green(PTE7,1); // 1 --> OFF, 0 --> ON - -void rgb_sel(int8_t idx) { - -switch(idx) { - case 0: - rgb_red = 0; rgb_blue=1; rgb_green = 1; - break; - case 1: - rgb_red = 1; rgb_blue=0; rgb_green = 1; - break; - case 2: - rgb_red = 1; rgb_blue=1; rgb_green = 0; - break; - } - -} - -// main() runs in its own thread in the OS -int main() { - int idx; - while (true) { - for(idx=0;idx<3;idx++) { - rgb_sel(idx); - wait(0.5); - } - } +/***************************************************************************//** + * @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" + + +/**************************** Define I/O **************************************/ + +/* LEDS */ +DigitalOut led_blue(LED_BLUE, 1); // 1 = OFF +DigitalOut led_red(LED_RED, 1); + +/* Rapid IoT Buttons */ +// InterruptIn in(PTA4); +InterruptIn in(PTE28); +InterruptIn inB1(PTE9); +// InterruptIn SW1(PTE8); +// DigitalIn SW3(PTE10); +// DigitalIn SW4(PTE28); + +DigitalOut lcd_light(PTE12, 1); // 1 = ON, 0 = OFF +ColorMemLCD display( PTB22, PTB23, PTB21, PTB20, PTD15, PTD9, "TFT"); + +/**************************** 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; + +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; + } +} + + +/* 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() +{ + /* Initialize pushbutton handlers */ + in.fall(in_handler_B0); + inB1.fall(in_handler_B1); + + /* 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 (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(); + } + } } \ No newline at end of file