the place we got to by the end of the last session

Dependencies:   LCDTFT TFT_fonts TSI mbed

Fork of ESP8266_MDM_CJS_KL25 by Oxford CWM Team

main.cpp

Committer:
trapsis
Date:
2016-06-10
Revision:
5:882898bb83ed
Parent:
4:354d278c0d52
Child:
6:00d91197dd66

File content as of revision 5:882898bb83ed:

#include "mbed.h"
#include "TSISensor.h"
#include "LCDTFT.h"
#include "Arial28x28.h"

#define DEBUG
#define INFOMESSAGES
#define WARNMESSAGES
#define ERRMESSAGES

#define FUNCNAME "MAIN"

#ifdef NoDEBUG
#define DBG(x, ...) pc.printf("    ["FUNCNAME" : DBG] "x" <line %d>\r\n", ##__VA_ARGS__,__LINE__);
#else
#define DBG(x, ...)
#endif

#ifdef ERRMESSAGES
#define ERR(x, ...) pc.printf(" ["FUNCNAME" : ERR] "x"\r\n", ##__VA_ARGS__);
#else
#define ERR(x, ...)
#endif

#ifdef WARNMESSAGES
#define WARN(x, ...) printf("["FUNCNAME" : WARN] "x"\r\n", ##__VA_ARGS__);
#else
#define WARN(x, ...)
#endif

#ifdef INFOMESSAGES
#define INFO(x, ...) pc.printf("["FUNCNAME" : INFO] "x"\r\n", ##__VA_ARGS__);
#else
#define INFO(x, ...)
#endif

#define BUFF_SIZE 1024
// PIN DEFS NOW FOR OLD FIRMWARE VERSION OF THE KL25Z
Serial  pc(USBTX, USBRX);
//RawSerial  dev(D1, D0);
//Serial  dev(PTD3,PTD2); //tx,rx
Serial  dev(D14,D15); //tx,rx
DigitalOut led1(LED1);
DigitalOut led4(LED3); // CHANGE TO LED 3
DigitalOut reset(D0,1);

PortOut MyPort(PortD ,0xFF); // define a port with only the lower 8 bits included - that'llbe PTD0-PTD7 making a single 8 bit port.
LCDTFT  MyLCD(PTB0,PTB1,PTB2,PTB3,PTC2,&MyPort);//LCDTFT(PinName PIN_RD,PinName PIN_WR,PinName PIN_RS,PinName PIN_CS,PinName PIN_RESET, PortOut *PORTLCD);


    PwmOut led(LED_GREEN);
    TSISensor tsi;
volatile int state=0;
volatile int ready=0;
//---
void run();
void countdown();
void changeDirec();
void nextmove();
void initGrid();
void updateGrid();
void drawGrid();
void checkposition();
void gameover1();
void gameover2();
void PrettyPrint(char *message,const unsigned char *font,short xpos,short ypos,short bcol, short fcol);
void prettyputc(char c, const unsigned char *font,short xpos,short ypos,short bcol, short fcol);

bool GameRunning = 1; 
const int gridWidth = 64;
const int gridHeight = 48;
char grid [48][64];
char snake [2][255];
//represent the grid as a 2 dimensional array

char newDirectSnake = 2;
char newDirectFood = 2;
char newFoodVel = 0;
//incoming values from the controller

int snakexpos = 20;
int snakeypos = 20;
char directSnake = 2;
char snakeSize = 3;
//establish values for the snake

int foodxpos = 2;
int foodypos = 20;
char foodvel = 1;
char directFood = 1;
//establish values for the food

char message [32];
//for printing purposes

int framecount = 0;
//number of iterations in the main loop
//-----
char ipAddress[20];
char macAddress[32];
char *buffer;
unsigned int bufferPnt=0;

void commandReceived(char *buffer){

    char identifier =buffer[0];
    if (identifier == 1) {                            
        newDirectFood=buffer[4];
        newFoodVel=buffer[8];        
  }
                        
    if (identifier == 2) {
        newDirectSnake=buffer[4];
  }
                        
    if (identifier == 3) {
        GameRunning=buffer[4];        
    }
 
}

// next two functions need moving to the library.....
// ok - a simple sub to put in a character from the fonts defined in TFT_fonts
// c= charactetr to put
// font = pointer to font to use
// x,y locatoin of bottom lh of character, bcol = background color, fcol = foreground color
//prettyputc("m",Arial12x12,50,50,ColorBlack,ColorWhite);
void prettyputc(char c, const unsigned char *font,short xpos,short ypos,short bcol, short fcol)
{
    // Length,horz,vert,byte/vert
    int length,hor,vert,bpver; // number of bytes per character, horizontal pixels, vertical pixels and bytes per column
    //
    int x,y,i,j,k,ptr;
    short coltowrite;
    char byte,point;
    length=font[0];
    hor=font[1];
    vert=font[2];
    bpver=font[3];
    for(i=0; i<hor; i++) { // loop over columns
        for(j=0; j<vert; j++) {
            x=xpos+i;
            y=ypos+j; // NB assumes colums stored from bottom to top.... ?
            ptr=((c -32) * length+1) + 4+i*bpver+(j/8);  // pointer in font array to start of the character we want +1 to avoid the first byte that holds the char width
            byte=(char)font[ptr];
            k=j%8; // number of the pixel in this byte
            point=byte & (1<<k); // get the next bit
            if(point>0) {
                coltowrite=fcol;
            } else {
                coltowrite=bcol;
            }

            MyLCD.vLCDTFTPoint(x,y,coltowrite);

        }
    }

}




// ok now a function to use pretty putc to write strings whose bottom left corner are at xpo,ypos
// general idea is that the string is first formatted byb sprintf and the PrettyPrint is called
// bcol and fcol are the backgroun adn foreground colors
//NB max message length = 64 characters
void PrettyPrint(char *message,const unsigned char *font,short xpos,short ypos,short bcol, short fcol)
{
    short x,y,messlength,i,ptr;
    messlength=strlen(message);
    if (messlength >64) messlength=64;  // avoid writing too large a string....
    x=xpos;
    for(i=0; i<messlength; i++) {
        // x=xpos+i*(font[1]*8/10); // font[1]=char width 80% to avoid gaps
        //pointer = &font[((c -32) * offset) + 4]; // start of char bitmap
        // w = pointer[0];                          // width of actual char
        ptr=((message[i] -32) * font[0]) + 4;

        y=ypos; // will have to add cod and more to deal with different screen orientations
        //prettyputc(char c, const unsigned char *font,short xpos,short ypos,short bcol, short fcol)
        prettyputc(message[i],font,x,y,bcol,fcol);
        x=x+font[ptr]+2;
    }

}


void run()
//the main game program
{
    while (1) {
        if (GameRunning == 1) {
            countdown();
            initGrid();
            while (1) {
                checkposition();
                commandReceived(buffer);
                changeDirec();
                nextmove();
                updateGrid();
                drawGrid();
                framecount++;
            }
        }
    }

}


void countdown()
//countdown before game begins
{
    MyLCD.vLCDTFTInit(1);
    MyLCD.vLCDTFTFillScreen(ColorBlack);

    sprintf(message,"Get Ready!");
    PrettyPrint(message,Arial28x28,10,50,ColorBlack,ColorLime);
    wait(1);

    MyLCD.vLCDTFTFillScreen(ColorBlack);
    sprintf(message,"3");
    PrettyPrint(message,Arial28x28,10,50,ColorBlack,ColorLime);
    wait(1);

    MyLCD.vLCDTFTFillScreen(ColorBlack);
    sprintf(message,"2");
    PrettyPrint(message,Arial28x28,10,50,ColorBlack,ColorLime);
    wait(1);

    MyLCD.vLCDTFTFillScreen(ColorBlack);
    sprintf(message,"1");
    PrettyPrint(message,Arial28x28,10,50,ColorBlack,ColorLime);
    wait(1);

    MyLCD.vLCDTFTFillScreen(ColorBlack);
    sprintf(message,"Run!");
    PrettyPrint(message,Arial28x28,10,50,ColorBlack,ColorLime);
    wait(1);

}

void initGrid()
//initialize the grid
{
    MyLCD.vLCDTFTInit(1);
    MyLCD.vLCDTFTFillScreen(ColorBlack);

    for(int x=0; x<gridHeight; x++) {
        for(int y=0; y<gridWidth; y++) {
            grid[x][y] = 0;
        }
    }
    //initialize the pixel grid as an array of zeros
    snake[0][0] = snakexpos;
    snake[1][0] = 20;
    snake[0][1] = 21;
    snake[1][1] = 20;
    snake[0][2] = 22;
    snake[1][2] = 20;

     for(int i=3; i<255; i++) {
        grid[snake[1][i]][snake[0][i]] = 0;
    }
    //initialize the snake as horizontal with respect to its initial size (1 = tile occupied by snake)

    grid[foodypos][foodxpos] = 2;
    //initialize the food (2 = tile occupied by food)
}

void updateGrid()
//update the grid with positions
{
    /*if (grid[snakexpos][snakeypos] == 1)
    gameover2();
        else
        {
        */    
        for(int a=snakeSize-2; a>=0; a--) {

         snake[0][a+1] = snake [0][a];
         snake[1][a+1] = snake [1][a];
       // }
        
        snake[0][0] = snakexpos;
        snake[1][0] = snakeypos;
    }

    for(int x=0; x<gridHeight; x++) {
        for(int y=0; y<gridWidth; y++) {
            grid[x][y] = 0;
        }
    }

    for(int i=0; i<snakeSize; i++) {
        grid[snake[1][i]][snake[0][i]] = 1;

    }
    //update the snake, if the tile was previously occupied, snake has hit itself = gameover2

    if (grid[foodypos][foodxpos] == 1) {
        gameover1();
    }

    else {
        grid[foodypos][foodxpos] = 2;
    }
    //update the food, if the tile was previously occupied, food has hit snake = gameover1
}


void drawGrid()
//draw the grid
{

    for(int x=0; x<gridHeight; x++) {
        for(int y=0; y<gridWidth; y++) {
          /*  if (grid[x][y] == 0) {
                MyLCD.vLCDTFTRectangle(5*y,5*x,5*y+5,5*x+5,1,ColorBlack);
            }
            */
            if (grid[x][y] == 1) {
                MyLCD.vLCDTFTRectangle(5*y,5*x,5*y+5,5*x+5,1,ColorBlue);
            }
            if (grid[x][y] == 2) {
                MyLCD.vLCDTFTRectangle(5*y,5*x,5*y+5,5*x+5,1,ColorWhite);
            }
        }
    }

     wait (0.1); //the game is 10fps (up for discussion we'll see how this goes)
}

void changeDirec()
//changing direction, the command will have to come from the controller program
//assume 0 for up, 1 for right, 2 for down, 3 for left
{
    foodvel = newFoodVel;
    directFood  =  newDirectFood;
    //assign new direction and speed to food

    if ((newDirectSnake + directSnake)%2 == 0 && newDirectSnake != directSnake)
    gameover2();
    //the snake loses if it tries to double up on itself

    else
    directSnake =  newDirectSnake;
    //assign new direction to snake
}


void nextmove()
//move the snake and the food by incrementing their coordinates (for the food increment by velocity)
{
    if (framecount%5 == 0){
        snakeSize++;
        }
    // every 5 iterations, the snake grows
   
    
    MyLCD.vLCDTFTRectangle(5*foodxpos,5*foodypos,5*foodxpos+5,5*foodypos+5,1,ColorBlack);
    MyLCD.vLCDTFTRectangle(5*snake[0][snakeSize-1],5*snake[1][snakeSize-1],5*snake[0][snakeSize-1]+5,5*snake[1][snakeSize-1]+5,1,ColorBlack);

    
    if (directFood == 0) {
        foodypos -= foodvel;
    }
    if (directFood == 1) {
        foodxpos += foodvel;
    }
    if (directFood == 2) {
        foodypos += foodvel;
    }
    if (directFood == 3) {
        foodxpos -= foodvel;
    }
    // check the direction of food and increment position according to velocity

    if (directSnake == 0) {
        snakeypos -= 1;
    }
    if (directSnake == 1) {
        snakexpos += 1;
    }
    if (directSnake == 2) {
        snakeypos += 1;
    }
    if (directSnake == 3) {
        snakexpos -= 1;
    }

}

void checkposition()
//check position to see if either player is out of bounds
{
    if (snakeypos > gridHeight || snakeypos < 0)
        gameover2();

    if (snakexpos > gridWidth || snakexpos < 0)
        gameover2();

    if (foodypos > gridHeight || foodypos < 0)
        gameover1();

    if (foodxpos > gridWidth || foodxpos < 0)
        gameover1();

    //end the game with the appropriate game over screen if either player is out of bounds
}


void gameover1()
//print game over message and display final score
{
    MyLCD.vLCDTFTFillScreen(ColorBlack);

    sprintf(message,"You are snake food!");
    PrettyPrint(message,Arial28x28,10,50,ColorBlack,ColorLime);


    GameRunning = 0;
}

void gameover2()
//an alternate ending is that the snake has made a mistake and that the food wins
{
    MyLCD.vLCDTFTFillScreen(ColorBlack);
    sprintf(message,"The snake is dead!");
    PrettyPrint(message,Arial28x28,10,50,ColorBlack,ColorLime);
    wait (1000);

    GameRunning = 0;
}

void dev_recv()
{
    char c;

    int count = 0;
    led1 = !led1;
    if(bufferPnt==0) {
        memset(buffer,0,BUFF_SIZE);
    }
    while(dev.readable()) {
        c = (char)dev.getc();
#ifdef DEBUG
       pc.putc(c);
#endif
        buffer[bufferPnt]=c;
        bufferPnt++;
        if (bufferPnt>1000) {
            ready=1;
        }
       // if ((c==0x0a)||(c==0x0d)){
        //     ready=1;
        //     }else
        if (c==0x0a) {
            if (bufferPnt>1) {
                if (buffer[bufferPnt -2]==0x0d) {
                    ready=1;
                    break;
                }
            }
        }
        if (!dev.readable()) {
            wait_us(10);
        }
    }
}

void pc_recv()
{
    char c;
    led4 = !led4;
    while(pc.readable()) {
        c=(char)pc.getc();
        dev.putc(c);
        pc.putc(c);
        if(c==13) {
            dev.putc(10);
            pc.putc(10);
            }

    }
}

char * OKResponse(char *test, const char *pattern)
{
    char *p= strstr(test,pattern);
    if (p==NULL) {
        //   DBG("Test=<%s> Patter=<%s> NULL [p=%s]",test,pattern,p);
        return NULL;
    } else {
        //  DBG("YAY Test=<%s> Patter=<%s>  [p=%s]",test,pattern,p);
    }
    return p;
}
/*Game programme
*/

int main()
{
    float touch;
    buffer=(char *)calloc(BUFF_SIZE,1);
    reset=0;
    int counter=0;
    pc.baud(115200);
    dev.baud(115200);
    pc.attach(&pc_recv, Serial::RxIrq);
    dev.attach(&dev_recv, Serial::RxIrq);
    pc.printf("Start up\n\r");
    wait(1.5);
    reset=1;
    char * resp=NULL;
    pc.printf("Here \n\r");
    while(1) {
        if (ready) {
            ready=0;
            bufferPnt=0;
            INFO("[%d],##%s##",state,buffer);
            switch (state) {
                case 0: {
                    resp=OKResponse(buffer,"WIFI GOT IP");
                    if (resp!=NULL) {
                        wait(1);
                        dev.printf("AT\r\n");
                        state++;
                    }
                    break;
                }
                case 1:
                case 2: {
                    resp=OKResponse(buffer,"OK");
                    if (resp!=NULL) {
                        dev.printf("AT\r\n");
                        state++;
                    }
                    break;
                }
                case 3: {
                    resp=OKResponse(buffer,"OK");
                    if (resp!=NULL) {
                        dev.printf("AT+RST\r\n");
                        state++;
                    }

                    break;
                }
                case 4: {
                    resp=OKResponse(buffer,"WIFI GOT IP");
                    if (resp!=NULL) {
                        dev.printf("AT+CWMODE=1\r\n");
                        state++;
                    }

                    break;
                }
                case 5: {
                    resp=OKResponse(buffer,"OK");
                    if (resp!=NULL) {
                        
                        dev.printf("AT+CWJAP=\"CWMWIFI\",\"CWM2016TT\"\r\n");
                        state++;
                    }

                    break;
                }
                case 6: {
                    resp=OKResponse(buffer,"OK");
                    if (resp!=NULL) {
                        wait(1);
                        dev.printf("AT+CIFSR\r\n");
                        state++;
                    }

                    break;
                }
                case 7: {
                    resp=OKResponse(buffer,"+CIFSR:STAIP,");
                    if (resp!=NULL) {
                        char *strt = strtok(buffer,"\"");
                        strcpy(ipAddress,strtok(NULL,"\""));
                        strtok(NULL,"\"");
                         strcpy(macAddress,strtok(NULL,"\""));
                        INFO("mac Address = %s", macAddress);
                        INFO("IP Address = %s", ipAddress);
                          dev.printf("AT+CIPMUX=1\r\n");
                        state++;
                    }

                    break;
                }
                case 8: {
                    resp=OKResponse(buffer,"OK");
                    if (resp!=NULL) {
                       INFO("Ready");
                       dev.printf("AT+CIPSERVER=1,5050\r\n");       //Set it as a server
                       state++;
                    }

                     break;
                }
                     
                case 9: {
                    resp=OKResponse(buffer,"+IPD");
                    if (resp!=NULL) {
                        INFO("Got <%s>",buffer);                                                                                                                             
                            commandReceived(buffer);                      // Interpret data
                            run();                                
                            state=9;                                // Keep on waiting for data
                        }   
                                       
                
                    
                    break;
                }
                
               /* case 9: {
                    resp=OKResponse(buffer,"OK");
                    if (resp!=NULL) {
                       INFO("Ready");
                       state++; 
                       dev.printf("AT+CIPSEND=4,10\r\n");
                    }

                     break;
                     }
                    case 10: {
                    resp=OKResponse(buffer,">");
                    if (resp!=NULL) {
                       INFO("SENDING");
                       state++; 
                       touch=tsi.readPercentage();
                       dev.printf("TSI=%1.2f\n\r",touch);
                       pc.printf("   ############  tsi=%1.2f\n\r",touch);
                       //INFO("sensor=%1.2f",float)tsi.readPercentage());
                    }
                    case 11: {
                    resp=OKResponse(buffer,"SEND OK");
                    if (resp!=NULL) {
                       INFO("SEND OK");
                       state=9; 
                       //wait(2);
                       }
                       wait(1);
                       state=9; 
                    }

                     break;
                }*/


            }
        }
        //__WFI(); // DELETED AS IT KILLS THE KL25 RESPONSIVITY
    }
}