Snake game on nokia N5110 LCD
Dependencies: mbed
Snake game on nokia N5110 LCD and Keyes Syos Joystick. You control snake using joystick. Start/pause game ba using button on joystick or by pressing p on your keyboard (serial communication). More info on my blog: http://sdizdarevic.com/post/94147065625/frdm-k64f-project
Revision 0:5bdb67970267, committed 2014-08-08
- Comitter:
- sdizdarevic
- Date:
- Fri Aug 08 06:44:50 2014 +0000
- Commit message:
- Check connections
Changed in this revision
diff -r 000000000000 -r 5bdb67970267 Helper.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Helper.h Fri Aug 08 06:44:50 2014 +0000 @@ -0,0 +1,59 @@ +#ifndef E_HELPER_H +#define E_HELPER_H +bool IsNum (const char C) +{ + return (C >= '0' && C <= '9'); +} +char ToUpper (const char C) +{ + if (C >= 'a' && C <= 'z') + return C - 32; + return C; +} +bool IsOurChar (const char C) +{ + char c = ToUpper (C); + return c == 'B' || c == 'R' || c == 'P' || c == 'Z' || c == 'H'; +} +int ToInt (const char C[]) +{ + int N = 0, i = 0; + while (C[i] != '\0') + { + if (IsNum (C[i])) + { + N = N * 10 + C[i++] - '0'; + } + else return -7; + } + return N; +} +int NumLen (int N) +{ + if (N == 0) return 1; + int C = 0; + while (N != 0) + { + C++; + N /= 10; + } + return C; +} +char *ToString (char Buff[], int N) +{ + if (N==0) + { + Buff[0] = '0'; + Buff[1] = '\0'; + return Buff; + } + int B = NumLen (N); + Buff[B] = '\0'; + while (N != 0) + { + Buff[--B] = N % 10 + '0'; + N /= 10; + } + return Buff; +} +#endif //E_HELPER_H
diff -r 000000000000 -r 5bdb67970267 N5110/N5110.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/N5110/N5110.cpp Fri Aug 08 06:44:50 2014 +0000 @@ -0,0 +1,259 @@ +/** +@file N5110.cpp + +@brief Member functions implementations + +*/ +#include "mbed.h" +#include "N5110.h" + + +N5110::N5110(PinName pwrPin, PinName scePin, PinName rstPin, PinName dcPin, PinName mosiPin, PinName sclkPin, PinName ledPin) +{ + + spi = new SPI(mosiPin,NC,sclkPin); // create new SPI instance and initialise + initSPI(); + + // set up pins as required + led = new PwmOut(ledPin); + pwr = new DigitalOut(pwrPin); + sce = new DigitalOut(scePin); + rst = new DigitalOut(rstPin); + dc = new DigitalOut(dcPin); + +} + +// initialise function - powers up and sends the initialisation commands +void N5110::init() +{ + turnOn(); // power up + wait_ms(10); // small delay seems to prevent spurious pixels during mbed reset + reset(); // reset LCD - must be done within 100 ms + + // function set - extended + sendCommand(0x20 | CMD_FS_ACTIVE_MODE | CMD_FS_HORIZONTAL_MODE | CMD_FS_EXTENDED_MODE); + // Don't completely understand these parameters - they seem to work as they are + // Consult the datasheet if you need to change them + sendCommand(CMD_VOP_7V38); // operating voltage - these values are from Chris Yan's Library + sendCommand(CMD_TC_TEMP_2); // temperature control + sendCommand(CMD_BI_MUX_48); // bias + + // function set - basic + sendCommand(0x20 | CMD_FS_ACTIVE_MODE | CMD_FS_HORIZONTAL_MODE | CMD_FS_BASIC_MODE); + normalMode(); // normal video mode by default + sendCommand(CMD_DC_NORMAL_MODE); // black on white + + // RAM is undefined at power-up so clear + clearRAM(); + +} + +// sets normal video mode (black on white) +void N5110::normalMode() { + sendCommand(CMD_DC_NORMAL_MODE); + +} + +// sets normal video mode (white on black) +void N5110::inverseMode() { + sendCommand(CMD_DC_INVERT_VIDEO); +} + +// function to power up the LCD and backlight +void N5110::turnOn() +{ + // set brightness of LED - 0.0 to 1.0 - default is 50% + setBrightness(0.5); + pwr->write(1); // apply power +} + +// function to power down LCD +void N5110::turnOff() +{ + setBrightness(0.0); // turn backlight off + clearRAM(); // clear RAM to ensure specified current consumption + // send command to ensure we are in basic model + sendCommand(0x20 | CMD_FS_ACTIVE_MODE | CMD_FS_HORIZONTAL_MODE | CMD_FS_BASIC_MODE); + // clear the display + sendCommand(CMD_DC_CLEAR_DISPLAY); + // enter the extended mode and power down + sendCommand(0x20 | CMD_FS_POWER_DOWN_MODE | CMD_FS_HORIZONTAL_MODE | CMD_FS_EXTENDED_MODE); + // small delay and then turn off the power pin + wait_ms(10); + pwr->write(0); + +} + +// function to change LED backlight brightness +void N5110::setBrightness(float brightness) +{ + // check whether brightness is within range + if (brightness < 0.0) + brightness = 0.0; + if (brightness > 1.0) + brightness = 1.0; + // set PWM duty cycle + led->write(brightness); +} + + +// pulse the active low reset line +void N5110::reset() +{ + rst->write(0); // reset the LCD + rst->write(1); +} + +// function to initialise SPI peripheral +void N5110::initSPI() +{ + spi->format(8,1); // 8 bits, Mode 1 - polarity 0, phase 1 - base value of clock is 0, data captured on falling edge/propagated on rising edge + spi->frequency(4000000); // maximum of screen is 4 MHz +} + +// send a command to the display +void N5110::sendCommand(unsigned char command) +{ + dc->write(0); // set DC low for command + sce->write(0); // set CE low to begin frame + spi->write(command); // send command + dc->write(1); // turn back to data by default + sce->write(1); // set CE high to end frame (expected for transmission of single byte) + +} + +// send data to the display at the current XY address +// dc is set to 1 (i.e. data) after sending a command and so should +// be the default mode. +void N5110::sendData(unsigned char data) +{ + sce->write(0); // set CE low to begin frame + spi->write(data); + sce->write(1); // set CE high to end frame (expected for transmission of single byte) +} + +// this function writes 0 to the 504 bytes to clear the RAM +void N5110::clearRAM() +{ + int i; + sce->write(0); //set CE low to begin frame + for(i = 0; i < 504; i++) { // 48 x 84 bits = 504 bytes + spi->write(0x00); // send 0's + } + sce->write(1); // set CE high to end frame + +} + +// function to set the XY address in RAM for subsequenct data write +void N5110::setXYAddress(int x, int y) +{ + // check whether address is in range + if (x > 83) + x=83; + if (y > 5) + y=5; + if (x < 0) + x=0; + if (y < 0) + y=0; + + sendCommand(0x80 | x); // send addresses to display with relevant mask + sendCommand(0x40 | y); +} + +// These functions are used to set, clear and get the value of pixels in the display +// Pixels are addressed in the range of 0 to 47 (y) and 0 to 83 (x). The refresh() +// function must be called after set and clear in order to update the display +void N5110::setPixel(int x, int y) +{ + // calculate bank and shift 1 to required position in the data byte + buffer[x][y/8] |= (1 << y%8); +} + +void N5110::clearPixel(int x, int y) +{ + // calculate bank and shift 1 to required position (using bit clear) + buffer[x][y/8] &= ~(1 << y%8); +} + +unsigned char N5110::getPixel(int x, int y) +{ + // return relevant bank and mask required bit + return buffer[x][y/8] & (1 << y%8); + +} + +// function to refresh the display +void N5110::refresh() +{ + int i,j; + sce->write(0); //set CE low to begin frame + + for(j = 0; j < 6; j++) { // be careful to use correct order (j,i) for horizontal addressing + for(i = 0; i < 84; i++) { + spi->write(buffer[i][j]); // send buffer + } + } + sce->write(1); // set CE high to end frame + +} + +// fills the buffer with random bytes. Can be used to test the display. +// The rand() function isn't seeded so it probably creates the same pattern everytime +void N5110::randomiseBuffer() +{ + int i,j; + for(j = 0; j < 6; j++) { // be careful to use correct order (j,i) for horizontal addressing + for(i = 0; i < 84; i++) { + buffer[i][j] = rand()%256; // generate random byte + } + } + +} + +// function to print 5x7 font +void N5110::printChar(char c) +{ + int i; + // loop through 5 columns + for (i = 0; i < 5 ; i++ ) { + sendData(font5x7[(c - 32)*5 + i]); + // array is offset by 32 relative to ASCII, each character is 5 pixels wide + // the X address is automatically incremented after each data write + } + sendData(0); // send an empty byte to introduce space between characters + +} + +// function to print string at specified position +void N5110::printString(const char * str,int x,int y) +{ + int n = 0 ; // counter for number of characters in string + // loop through string and print character + while(*str) { + + setXYAddress(x+6*n,y); // leave 1 pixel (6 = 5 + 1) between each character + printChar(*str); // print the char - can probably so *str++ and remove next line + str++; // go to next character in string + n++; // increment index + } + +} + +// function to clear the screen +void N5110::clear() +{ + clearBuffer(); // clear the buffer then call the refresh function + refresh(); +} + +// function to clear the buffer +void N5110::clearBuffer() +{ + int i,j; + for (i=0; i<84; i++) { // loop through the banks and set the buffer to 0 + for (j=0; j<6; j++) { + buffer[i][j]=0; + } + } +}
diff -r 000000000000 -r 5bdb67970267 N5110/N5110.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/N5110/N5110.h Fri Aug 08 06:44:50 2014 +0000 @@ -0,0 +1,318 @@ +/** +@file N5110.h + +@brief Header file containing member functions and variables + +*/ + +#ifndef N5110_H +#define N5110_H + +// Command Bytes - taken from Chris Yan's library +// More information can be found in the display datasheet +// H = 0 - Basic instructions +#define CMD_DC_CLEAR_DISPLAY 0x08 +#define CMD_DC_NORMAL_MODE 0x0C +#define CMD_DC_FILL_DISPLAY 0x09 +#define CMD_DC_INVERT_VIDEO 0x0D +#define CMD_FS_HORIZONTAL_MODE 0x00 +#define CMD_FS_VERTICAL_MODE 0x02 +#define CMD_FS_BASIC_MODE 0x00 +#define CMD_FS_EXTENDED_MODE 0x01 +#define CMD_FS_ACTIVE_MODE 0x00 +#define CMD_FS_POWER_DOWN_MODE 0x04 +// H = 1 - Extended instructions +#define CMD_TC_TEMP_0 0x04 +#define CMD_TC_TEMP_1 0x05 +#define CMD_TC_TEMP_2 0x06 +#define CMD_TC_TEMP_3 0x07 +#define CMD_BI_MUX_24 0x15 +#define CMD_BI_MUX_48 0x13 +#define CMD_BI_MUX_100 0x10 +#define CMD_VOP_6V06 0xB2 +#define CMD_VOP_7V38 0xC8 + +#include "mbed.h" + +/** +@brief Simple library for interfacing with Nokia 5110 LCD display (https://www.sparkfun.com/products/10168) using the hardware SPI on the mbed. +@brief The display is powered from a GPIO pin meaning it can be controlled via software. The LED backlight is also software-controllable (via PWM pin). +@brief Can print characters and strings to the display using the included 5x7 font. +@brief The library also implements a screen buffer so that individual pixels on the display (84 x 48) can be set, cleared and read. + +@brief Acknowledgements to Chris Yan's Nokia_5110 Library. + +@brief Revision 1.0 + +@author Craig A. Evans +@date January 2014 + * + * Example: + * @code + + #include "mbed.h" + #include "N5110.h" + + // VCC,SCE,RST,D/C,MOSI,SCLK,LED + N5110 lcd(p7,p8,p9,p10,p11,p13,p26); + + int main() { + + // initialise display + lcd.init(); + // print a string in top-left corner + lcd.printString("Hello, World!",0,0); + // move cursor to 4th row + lcd.setXYAddress(0,3); + // print character + lcd.printChar('X'); + + while(1); + } + + * @endcode + */ +class N5110 +{ + +public: + /** Create a N5110 object connected to the specified pins + * + * @param pwr Pin connected to Vcc on the LCD display (pin 1) + * @param sce Pin connected to chip enable (pin 3) + * @param rst Pin connected to reset (pin 4) + * @param dc Pin connected to data/command select (pin 5) + * @param mosi Pin connected to data input (MOSI) (pin 6) + * @param sclk Pin connected to serial clock (SCLK) (pin 7) + * @param led Pin connected to LED backlight (must be PWM) (pin 8) + * + */ + N5110(PinName pwrPin, PinName scePin, PinName rstPin, PinName dcPin, PinName mosiPin, PinName sclkPin, PinName ledPin); + + /** Initialise display + * + * Powers up the display and turns on backlight (50% brightness default). + * Sets the display up in horizontal addressing mode and with normal video mode. + */ + void init(); + + /** Turn off + * + * Powers down the display and turns of the backlight. + * Needs to be reinitialised before being re-used. + */ + void turnOff(); + + /** Clears + * + * Clears the screen. + */ + void clear(); + + /** Turn on normal video mode (default) + * Black on white + */ + void normalMode(); + + /** Turn on inverse video mode (default) + * White on black + */ + void inverseMode(); + + /** Set Brightness + * + * Sets brightness of LED backlight. + * @param brightness - float in range 0.0 to 1.0 + */ + void setBrightness(float brightness); + + /** Set XY Address + * + * Sets the X and Y address of where the next data sent to the displa will be written in RAM. + * @param x - the column number (0 to 83) - is automatically incremented after data is written + * @param y - the row number (0 to 5) - the diplay is split into 6 banks - each bank can be considered a row + */ + void setXYAddress(int x, int y); + + /** Print String + * + * Prints a string of characters to the display. + * @param x - the column number (0 to 83) + * @param y - the row number (0 to 5) - the display is split into 6 banks - each bank can be considered a row + */ + void printString(const char * str,int x,int y); + + /** Print Character + * + * Sends a character to the display. Will be printed at the current address. + * X address is autoincremented by 1 to leave a pixel between successive characters. + * @param c - the character to print. Can print ASCII as so printChar('C'). + */ + void printChar(char c); + + /** Set a Pixel + * + * This function sets a pixel in the display. A call to refresh() must be made + * to update the display to reflect the change in pixels. + * @param x - the x co-ordinate of the pixel (0 to 83) + * @param y - the y co-ordinate of the pixel (0 to 47) + */ + void setPixel(int x, int y); + + /** Clear a Pixel + * + * This function clears pixel in the display. A call to refresh() must be made + * to update the display to reflect the change in pixels. + * @param x - the x co-ordinate of the pixel (0 to 83) + * @param y - the y co-ordinate of the pixel (0 to 47) + */ + void clearPixel(int x, int y); + + /** Get a Pixel + * + * This function gets the status of a pixel in the display. + * @param x - the x co-ordinate of the pixel (0 to 83) + * @param y - the y co-ordinate of the pixel (0 to 47) + * @returns + * 0 - pixel is clear + * non-zero - pixel is set + */ + unsigned char getPixel(int x, int y); + + /** Refresh display + * + * This functions refreshes the display to reflect the current data in the buffer. + */ + void refresh(); + + /** Randomise buffer + * + * This function fills the buffer with random data. Can be used to test the display. + * A call to refresh() must be made to update the display to reflect the change in pixels. + * The seed is not set and so the generated pattern will probably be the same each time. + * TODO: Randomise the seed - maybe using the noise on the AnalogIn pins. + */ + void randomiseBuffer(); + +private: + void initSPI(); + void turnOn(); + void reset(); + void clearRAM(); + void clearBuffer(); + void sendCommand(unsigned char command); + void sendData(unsigned char data); + +public: + unsigned char buffer[84][6]; // screen buffer - the 6 is for the banks - each one is 8 bits; + +private: // private variables + SPI* spi; + PwmOut* led; + DigitalOut* pwr; + DigitalOut* sce; + DigitalOut* rst; + DigitalOut* dc; + +}; + +const unsigned char font5x7[480] = { + 0x00, 0x00, 0x00, 0x00, 0x00,// (space) + 0x00, 0x00, 0x5F, 0x00, 0x00,// ! + 0x00, 0x07, 0x00, 0x07, 0x00,// " + 0x14, 0x7F, 0x14, 0x7F, 0x14,// # + 0x24, 0x2A, 0x7F, 0x2A, 0x12,// $ + 0x23, 0x13, 0x08, 0x64, 0x62,// % + 0x36, 0x49, 0x55, 0x22, 0x50,// & + 0x00, 0x05, 0x03, 0x00, 0x00,// ' + 0x00, 0x1C, 0x22, 0x41, 0x00,// ( + 0x00, 0x41, 0x22, 0x1C, 0x00,// ) + 0x08, 0x2A, 0x1C, 0x2A, 0x08,// * + 0x08, 0x08, 0x3E, 0x08, 0x08,// + + 0x00, 0x50, 0x30, 0x00, 0x00,// , + 0x08, 0x08, 0x08, 0x08, 0x08,// - + 0x00, 0x60, 0x60, 0x00, 0x00,// . + 0x20, 0x10, 0x08, 0x04, 0x02,// / + 0x3E, 0x51, 0x49, 0x45, 0x3E,// 0 + 0x00, 0x42, 0x7F, 0x40, 0x00,// 1 + 0x42, 0x61, 0x51, 0x49, 0x46,// 2 + 0x21, 0x41, 0x45, 0x4B, 0x31,// 3 + 0x18, 0x14, 0x12, 0x7F, 0x10,// 4 + 0x27, 0x45, 0x45, 0x45, 0x39,// 5 + 0x3C, 0x4A, 0x49, 0x49, 0x30,// 6 + 0x01, 0x71, 0x09, 0x05, 0x03,// 7 + 0x36, 0x49, 0x49, 0x49, 0x36,// 8 + 0x06, 0x49, 0x49, 0x29, 0x1E,// 9 + 0x00, 0x36, 0x36, 0x00, 0x00,// : + 0x00, 0x56, 0x36, 0x00, 0x00,// ; + 0x00, 0x08, 0x14, 0x22, 0x41,// < + 0x14, 0x14, 0x14, 0x14, 0x14,// = + 0x41, 0x22, 0x14, 0x08, 0x00,// > + 0x02, 0x01, 0x51, 0x09, 0x06,// ? + 0x32, 0x49, 0x79, 0x41, 0x3E,// @ + 0x7E, 0x11, 0x11, 0x11, 0x7E,// A + 0x7F, 0x49, 0x49, 0x49, 0x36,// B + 0x3E, 0x41, 0x41, 0x41, 0x22,// C + 0x7F, 0x41, 0x41, 0x22, 0x1C,// D + 0x7F, 0x49, 0x49, 0x49, 0x41,// E + 0x7F, 0x09, 0x09, 0x01, 0x01,// F + 0x3E, 0x41, 0x41, 0x51, 0x32,// G + 0x7F, 0x08, 0x08, 0x08, 0x7F,// H + 0x00, 0x41, 0x7F, 0x41, 0x00,// I + 0x20, 0x40, 0x41, 0x3F, 0x01,// J + 0x7F, 0x08, 0x14, 0x22, 0x41,// K + 0x7F, 0x40, 0x40, 0x40, 0x40,// L + 0x7F, 0x02, 0x04, 0x02, 0x7F,// M + 0x7F, 0x04, 0x08, 0x10, 0x7F,// N + 0x3E, 0x41, 0x41, 0x41, 0x3E,// O + 0x7F, 0x09, 0x09, 0x09, 0x06,// P + 0x3E, 0x41, 0x51, 0x21, 0x5E,// Q + 0x7F, 0x09, 0x19, 0x29, 0x46,// R + 0x46, 0x49, 0x49, 0x49, 0x31,// S + 0x01, 0x01, 0x7F, 0x01, 0x01,// T + 0x3F, 0x40, 0x40, 0x40, 0x3F,// U + 0x1F, 0x20, 0x40, 0x20, 0x1F,// V + 0x7F, 0x20, 0x18, 0x20, 0x7F,// W + 0x63, 0x14, 0x08, 0x14, 0x63,// X + 0x03, 0x04, 0x78, 0x04, 0x03,// Y + 0x61, 0x51, 0x49, 0x45, 0x43,// Z + 0x00, 0x00, 0x7F, 0x41, 0x41,// [ + 0x02, 0x04, 0x08, 0x10, 0x20,// "\" + 0x41, 0x41, 0x7F, 0x00, 0x00,// ] + 0x04, 0x02, 0x01, 0x02, 0x04,// ^ + 0x40, 0x40, 0x40, 0x40, 0x40,// _ + 0x00, 0x01, 0x02, 0x04, 0x00,// ` + 0x20, 0x54, 0x54, 0x54, 0x78,// a + 0x7F, 0x48, 0x44, 0x44, 0x38,// b + 0x38, 0x44, 0x44, 0x44, 0x20,// c + 0x38, 0x44, 0x44, 0x48, 0x7F,// d + 0x38, 0x54, 0x54, 0x54, 0x18,// e + 0x08, 0x7E, 0x09, 0x01, 0x02,// f + 0x08, 0x14, 0x54, 0x54, 0x3C,// g + 0x7F, 0x08, 0x04, 0x04, 0x78,// h + 0x00, 0x44, 0x7D, 0x40, 0x00,// i + 0x20, 0x40, 0x44, 0x3D, 0x00,// j + 0x00, 0x7F, 0x10, 0x28, 0x44,// k + 0x00, 0x41, 0x7F, 0x40, 0x00,// l + 0x7C, 0x04, 0x18, 0x04, 0x78,// m + 0x7C, 0x08, 0x04, 0x04, 0x78,// n + 0x38, 0x44, 0x44, 0x44, 0x38,// o + 0x7C, 0x14, 0x14, 0x14, 0x08,// p + 0x08, 0x14, 0x14, 0x18, 0x7C,// q + 0x7C, 0x08, 0x04, 0x04, 0x08,// r + 0x48, 0x54, 0x54, 0x54, 0x20,// s + 0x04, 0x3F, 0x44, 0x40, 0x20,// t + 0x3C, 0x40, 0x40, 0x20, 0x7C,// u + 0x1C, 0x20, 0x40, 0x20, 0x1C,// v + 0x3C, 0x40, 0x30, 0x40, 0x3C,// w + 0x44, 0x28, 0x10, 0x28, 0x44,// x + 0x0C, 0x50, 0x50, 0x50, 0x3C,// y + 0x44, 0x64, 0x54, 0x4C, 0x44,// z + 0x00, 0x08, 0x36, 0x41, 0x00,// { + 0x00, 0x00, 0x7F, 0x00, 0x00,// | + 0x00, 0x41, 0x36, 0x08, 0x00,// } + 0x08, 0x08, 0x2A, 0x1C, 0x08,// -> + 0x08, 0x1C, 0x2A, 0x08, 0x08 // <- +}; + +#endif
diff -r 000000000000 -r 5bdb67970267 Snakelib.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Snakelib.h Fri Aug 08 06:44:50 2014 +0000 @@ -0,0 +1,341 @@ +#ifndef E_SNAKE_H +#define E_SNAKE_H +#include <cstdlib> +#include "mbed.h" +#include "N5110.h" +#include "Helper.h" +class Snakelib + { + static const bool SnakeTypes [2][6][3][3]; + static const bool SnakeFood [5][3][3]; + static const int Pos [2][3][3]; + short Snake [438][2]; + static const double Speeds [10]; + static const unsigned char Points[10]; + AnalogIn VX, VY; + InterruptIn SW; + int HScore, Score; + int SnakeLen, Speed; + int SnakeType, FoodType; + int eX, eY, pX, pY, Dir; + bool Moved, Pause, Draw, Started; + N5110 DISP; + DigitalOut ENBL; + Ticker TJoy, TMove; + Timer Dbnc; + Ticker T; + void SetBlock (int Block = 0, int X = 1, int Y = 1) + { + for (int a = 0; a < 3; ++a) + for (int b = 0; b < 3; ++b) + if (Block == 2 && SnakeFood [FoodType][a][b]) + DISP.setPixel (X + Pos[0][a][b], Y + Pos[1][a][b]); + else if (Block < 2 && SnakeTypes [Block][SnakeType][a][b]) + DISP.setPixel (X + Pos[0][a][b], Y + Pos[1][a][b]); + } + int Rand (int Min = 1, int Max = 83) + { + static bool First = true; + if (First) srand (time (NULL)), First = false; + while (7) + { + int S = rand () % (Max - Min + 1) + Min; + if (!((S - 1) % 3)) return S; + } + } + void GameOver () + { + + //FlashB(); + wait (2); + DISP.clear(); + DISP.setXYAddress (0, 0); + DISP.printString ("END!", 29, 0); + DISP.printString ("Score: ", 10, 2); + char Buff[20]; + ToString (Buff, Score); + DISP.printString (Buff, 50, 2); + DISP.printString ("Best: ", 10, 4); + ToString (Buff, HScore); + DISP.printString (Buff, 50, 4); + eX = eY = 0; // + Started = false; + wait (3); + Restart(); + } + void Prekuco() + { + DISP.clear(); + DISP.setXYAddress (0, 0); + DISP.printString ("Well done!!!!!", 0, 0); + DISP.printString ("Congrats", 0, 2); + eX = eY = 0; + Started = false; + wait (3); + Restart(); + } + void HitFood () + { + if (Snake [0][0] == pX && Snake [0][1] == pY) + { + Score += Points[Speed - 1]; + AddSnakeBody(); + RandFood(pX, pY); + } + } + void HitWall() + { + if (Snake[0][0] + 1 > 83 || Snake[0][0] - 1 < 0 || Snake[0][1] + 1 > 47 || Snake[0][1] - 1 < 0) + { + if (Score > HScore) + HScore = Score; + Started = false;; + GameOver(); + return; + } + } + void HitSelf() + { + for (int a = 1; a <= SnakeLen; ++a) + if (Snake[0][0] == Snake[a][0] && Snake[0][1] == Snake[a][1]) + { + if (Score > HScore) + HScore = Score; + GameOver(); + return; + } + } + void Start() + { + Snake[0][0] = Rand(20, 70); + Snake[0][1] = Rand(10, 35); + RandFood(pX, pY); + AddSnakeBody(); + AddSnakeBody(); + Refresh(); + } + void FlashB () + { + for (int z = 0; z < 5; ++z) + { + DISP.clear(); + DISP.setXYAddress (0, 0); + DISP.refresh(); + wait (0.5); + DrawWall(); + for (int a = 0; a <= SnakeLen; ++a) + SetBlock(a == 0 ? 0 : 1, Snake[a][0], Snake[a][1]); + SetBlock(2, pX, pY); + DISP.refresh(); + } + } + void MoveSnake () + { + if (Pause || !Started) return; + for (int a = SnakeLen; a >= 1; --a) + { + Snake[a][0] = Snake[a - 1][0]; + Snake[a][1] = Snake[a - 1][1]; + } + Snake[0][0] += eX; + Snake[0][1] += eY; + Moved = true; + Refresh(); + } + void AddSnakeBody() + { + SnakeLen++; + int X = 0, Y = 0; + if (Dir == 0) X = 3, Y = 0; + if (Dir == 1) X = 0, Y = 3; + if (Dir == 2) X = -3, Y = 0; + if (Dir == 3) X = 0, Y = -3; + Snake [SnakeLen][0] = Snake[SnakeLen - 1][0] + X; + Snake [SnakeLen][1] = Snake[SnakeLen - 1][1] + Y; + } + void RandFood(int &X, int &Y) + { + while (7) + { + int A = Rand(1, 83); + int B = Rand(1, 47); + bool S = false; + for (int I = 0; I <= SnakeLen; ++I) + if (Snake[I][0] == A && Snake[I][1] == B) + S = true; + if (!S) {X = A; Y = B; return;} + } + } + void DrawWall () + { + for (int a = 0; a < 84; ++a) + for (int b = 0; b < 48; ++b) + if (!a || !b || a == 83 || b == 47) + DISP.setPixel (a, b); + } + void Refresh () + { + if (!Draw) return; + HitFood(); + HitWall(); + HitSelf(); + DISP.clear(); + DISP.setXYAddress (0, 0); + DrawWall(); + for (int a = 0; a <= SnakeLen; ++a) + SetBlock(a == 0 ? 0 : 1, Snake[a][0], Snake[a][1]); + SetBlock(2, pX, pY); + DISP.refresh(); + if (SnakeLen > 437) Prekuco(); + } + void Moving () + { + if (!Moved) return; + double vx = VX, vy = VY; + if (vx < 1./3.) + { + if (Dir == 2) return; + eX = -3; eY = 0; + Dir = 0; + Moved = false; + } + else if (vx > 2./3.) + { + if (Dir == 0) return; + eX = 3; eY = 0; + Dir = 2; + Moved = false; + } + if (vy < 1./3.) + { + if (Dir == 1) return; + eX = 0; eY = -3; + Dir = 3; + Moved = false; + } + else if (vy > 2./3.) + { + if (Dir == 3) return; + eX = 0; eY = 3; + Dir = 1; + Moved = false; + } + } + void Pressed () + { + if (Dbnc.read() > .2) + { + if (!Started) + { + Started = true; + TMove.attach (this, &Snakelib::MoveSnake, Speeds[Speed - 1]); + } + else + { + Pause = !Pause; + Draw = !Pause; + } + } + Dbnc.reset(); + } + public: + Snakelib (PinName P1, PinName P2, PinName P3, PinName P4, PinName P5, + PinName P6, PinName P7, PinName BX, PinName BY, PinName BS) + : VX (BX), VY (BY), SW (BS), HScore (0), Score (0), SnakeLen (0), Speed (6), SnakeType (0), + FoodType (0), eX (3), eY (0), pX(0), pY (0), Dir (2), Moved(false), Pause (false), Draw (true), Started (false), + DISP (P1, P2, P3, P4, P5, P6, P7), ENBL (LED_RED) + { + + } + void START() + { + ENBL = 1; + Dbnc.start(); + SW.mode (PullUp); + DISP.init(); + DISP.setXYAddress (0, 0); + DISP.clear(); + TJoy.attach (this, &Snakelib::Moving, 0.01); + DISP.printString ("- SNAKE -", 0, 0); + DISP.printString ("K64F", 0, 3); + DISP.printString ("Freescale", 0, 4); + wait (2); + SW.rise (this, &Snakelib::Pressed); + Start(); + + + } + int SnakeSpeed () const {return Speed;} + void SetSnakeSpeed (unsigned char S) + { + if (S == Speed) return; + Speed = S; + Speed = Speed < 1 ? 1 : Speed > 10 ? 10 : Speed; + TMove.detach(); + wait_ms (2); + TMove.attach (this, &Snakelib::MoveSnake, Speeds[Speed - 1]); + } + int GetSnakeType () const {return SnakeType + 1;} + void SetSnakeType (unsigned char S) + { + if (S == SnakeType) return; + int ST = S < 1 ? 1 : S > 6 ? 6 : S; + SnakeType = ST - 1; + Refresh(); + } + int GetFoodType () const {return FoodType + 1;} + void SetFoodType (unsigned char S) + { + if (S == FoodType) return; + int FT = S < 1 ? 1 : S > 5 ? 5 : S; + FoodType = FT - 1; + Refresh(); + } + void PauseGame () {Pause = true; Draw = false;} + void ResumeGame () {Pause = false; Draw = true;} + bool Paused () const {return Pause;} + void Restart() + { + TMove.detach(); + SnakeLen = eY = Score = 0; + eX = 3; + Dir = 2; + Started = false; + Start(); + } + }; +const bool Snakelib::SnakeTypes [2][6][3][3] = + { + { + {{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + {{1, 1, 1}, {1, 0, 1}, {1, 1, 1}}, + {{0, 1, 0}, {1, 1, 1}, {0, 1, 0}}, + {{0, 1, 0}, {1, 0, 1}, {0, 1, 0}}, + {{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + {{1, 1, 1}, {1, 0, 1}, {1, 1, 1}} + }, + { + {{1, 1, 1}, {1, 0, 1}, {1, 1, 1}}, + {{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + {{0, 1, 0}, {1, 0, 1}, {0, 1, 0}}, + {{0, 1, 0}, {1, 1, 1}, {0, 1, 0}}, + {{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + {{1, 1, 1}, {1, 0, 1}, {1, 1, 1}} + } + }; +const bool Snakelib::SnakeFood [5][3][3] = + { + {{1, 0, 1}, {0, 1, 0}, {1, 0, 1}}, + {{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, + {{1, 1, 1}, {1, 0, 1}, {1, 1, 1}}, + {{0, 1, 0}, {1, 1, 1}, {0, 1, 0}}, + {{0, 1, 0}, {1, 0, 1}, {0, 1, 0}} + }; +const int Snakelib::Pos [2][3][3] = + { + {{-1, 0, 1}, {-1, 0, 1}, {-1, 0, 1}}, + {{1, 1, 1}, {0, 0, 0}, {-1, -1, -1}} + }; +const double Snakelib::Speeds [10] = {1., .8, .7, .5, .32, .25, .15, .1, .075, .050}; +const unsigned char Snakelib::Points[10] = {1, 1, 1, 2, 3, 4, 5, 6, 8, 10}; +#endif //E_SNAKE_H
diff -r 000000000000 -r 5bdb67970267 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Fri Aug 08 06:44:50 2014 +0000 @@ -0,0 +1,53 @@ +#include "mbed.h" +#include "Snakelib.h" +#include "Helper.h" +Serial PC (USBTX, USBRX); +Ticker T; + +//Very important to connect! Snakelib class parametters from N5110 lcd (VCC,SCE, RST,D/C, MOSI,SCLK,LED) and the last 3 from joystick + +Snakelib Snake (PTB2, PTD0, PTB9, PTB3, PTD2, PTD1, PTD0, PTB11, PTC11, PTC10); +void Start() + { + if (!PC.readable()) return; + char C = PC.getc(); + while (!IsOurChar (C)) C = PC.getc(); + C = ToUpper (C); + static char Buff[4] = "000"; + if (C == 'B' || C == 'Z' || C == 'H') + { + int N = -7; + if (C == 'B') //B01 - B10 + { + Buff[0] = PC.getc(); + Buff[1] = PC.getc(); + N = ToInt (Buff); + if (N == -7) return; + Snake.SetSnakeSpeed (N); + PC.printf ("\nSnake speed changed to %d\n", N); + return; + } + Buff[0] = PC.getc(); + Buff[1] = 0; + if ((N = ToInt (Buff)) == -7) return; + if (C == 'Z') {Snake.SetSnakeType (N); PC.printf ("\nSnake type changed to %d\n", N);} + else {Snake.SetFoodType (N); PC.printf ("\nSnake food changed to %d\n", N);} + } + else if (C == 'P') + { + if (Snake.Paused()) Snake.ResumeGame(), PC.printf ("\nContinuing...\n"); + else Snake.PauseGame(), PC.printf ("\nPause...\n"); + } + else if (C == 'R') Snake.Restart(), PC.printf ("\nRestarted!\n"); + } +int main () + { + + PC.printf ("\nManual:\n\n-P -> Pause/Continue\n-Z# -> Change snake type. Allowed values Z1-Z6\n"); + PC.printf ("-H# -> Change snake food. Allowed values H1-H5\n-R -> Restart game\n"); + PC.printf ("-B# -> Change snake speed. Allowed B01-B10\n"); + PC.printf ("\nTemp settings: B6, Z1, H1\nTo start playing, use joystick.\n\n \n\n"); + T.attach (&Start, 0.01); + Snake.START(); + while (7); + }
diff -r 000000000000 -r 5bdb67970267 mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Fri Aug 08 06:44:50 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/6213f644d804 \ No newline at end of file