Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include "NUC100Series.h"
- #include "MCU_init.h"
- #include "SYS_init.h"
- #include "LCD.h"
- #include "Draw2D.h"
- #include "picture.h"
- #define SYSTICK_DLAY_us 1000000
- #define Xmax 128
- #define Ymax 64
- #define Xmin 1
- #define Ymin 1
- #define BLOCK_HEIGHT 6
- #define BLOCK_WIDTH 6
- #define GOAL 20
- //------------------------------------------------------------------------------------------------------------------------------------
- // Functions declaration
- //------------------------------------------------------------------------------------------------------------------------------------
- void System_Config(void);
- void SPI3_Config(void);
- void LCD_start(void);
- void LCD_command(unsigned char temp);
- void LCD_data(unsigned char temp);
- void LCD_clear(void);
- void LCD_SetAddress(uint8_t PageAddr, uint8_t ColumnAddr);
- void KeyPadEnable(void);
- uint8_t KeyPadScanning(void);
- uint8_t collision(uint8_t x, uint8_t y, uint8_t tx, uint8_t ty);
- uint8_t rand(uint8_t axis, uint8_t current);
- void addLast(uint8_t x, uint8_t y);
- void shift(uint8_t nx, uint8_t ny);
- //------------------------------------------------------------------------------------------------------------------------------------
- // Main program
- //------------------------------------------------------------------------------------------------------------------------------------
- typedef enum {welcome_screen, game_rules, game_background, main_game, end_game} STATES;
- typedef struct {
- uint8_t x, y;
- } Coordinate;
- Coordinate coords[GOAL]; //global snake coords
- uint8_t ate = 0, size = 1;
- int main(void)
- {
- STATES game_state;
- uint8_t i, key_pressed=0, game_pad=0;
- uint8_t x=64, y=32, dx=0, dy=0;
- uint8_t x_steps, y_steps;
- uint8_t x_reset, y_reset;
- char score_txt[]="0";
- uint8_t tx = 8, ty = 8; //target
- uint8_t nx, ny;
- uint8_t reset_counter;
- //--------------------------------
- //System initialization
- //--------------------------------
- System_Config();
- KeyPadEnable();
- //--------------------------------
- //SPI3 initialization
- //--------------------------------
- SPI3_Config();
- //--------------------------------
- //LCD initialization
- //--------------------------------
- LCD_start();
- LCD_clear();
- //--------------------------------
- //LCD static content
- //--------------------------------
- //--------------------------------
- //LCD dynamic content
- //--------------------------------
- game_state = welcome_screen;
- x_steps = 2; y_steps = 2;//x_steps = BLOCK_WIDTH; y_steps = BLOCK_HEIGHT;
- x_reset = 64; y_reset = 32;
- //initially map all coords to (-1,-1) and dx,dy to (0,0);
- for (i=0; i<GOAL; i++) {
- coords[i].x = -BLOCK_WIDTH; //makes it hidden outside of viewport
- coords[i].y = -BLOCK_HEIGHT;
- }
- while (1) {
- switch(game_state){
- case welcome_screen:
- //welcome state code here
- draw_LCD(monster_128x64);
- for (i=0;i<3;i++) CLK_SysTickDelay(SYSTICK_DLAY_us);
- LCD_clear();
- game_state = game_rules; // state transition
- break;
- case game_rules:
- // game_rules state code here
- printS_5x7(1, 0, "Use Keypad to control");
- printS_5x7(1, 8, "2: UP 4: LEFT");
- printS_5x7(1, 16, "6: RIGHT 8: DOWN");
- printS_5x7(1, 32, "Eat all boxes to win");
- printS_5x7(1, 39, "press any key to continue!");
- while(key_pressed==0) key_pressed = KeyPadScanning();
- key_pressed=0;
- LCD_clear();
- game_state = game_background;
- break;
- case game_background:
- // static display information should be here
- sprintf(score_txt, "%d", ate);
- printS_5x7(48, 0, score_txt);
- fill_Rectangle(tx, ty, tx+BLOCK_WIDTH, ty+BLOCK_HEIGHT, 1, 0);
- game_state = main_game;
- case main_game:
- //main_game state code here
- //display snake
- for (i=0; i<size; i++) {
- fill_Rectangle(coords[i].x, coords[i].y, coords[i].x+BLOCK_WIDTH, coords[i].y+BLOCK_HEIGHT, 1, 0);
- /*
- if (collision(x, y, coords[i].x, coords[i].y)) { //steppped on ourselves
- ate = 0;
- size = 1; // start again with 1 block
- }
- */
- }
- game_pad = KeyPadScanning();
- CLK_SysTickDelay(170000); //delay for vision
- //hide snake
- for (i=0; i<size; i++)
- fill_Rectangle(coords[i].x, coords[i].y, coords[i].x+BLOCK_WIDTH, coords[i].y+BLOCK_HEIGHT, 0, 0);
- //check changes
- switch(game_pad) {
- case 1:
- dx =-1; dy =-1;
- break;
- case 2:
- dx = 0; dy = -1;
- break;
- case 3:
- dx = +1; dy =-1;
- break;
- case 4:
- dx = -1; dy = 0;
- break;
- case 5:
- dx = dy = 0;
- reset_counter++;
- if (reset_counter >= 5)
- game_state = end_game;
- break;
- case 6:
- dx = +1; dy = 0;
- break;
- case 7:
- dx = -1; dy= +1;
- break;
- case 8:
- dx = 0; dy= +1;
- break;
- case 9:
- dx=+1; dy=+1;
- break;
- default:
- reset_counter = 0;
- break;
- }
- game_pad = 0;
- //update object’s information (position, etc.)
- nx = x + dx * x_steps;
- ny = y + dy * y_steps;
- //update head
- shift(x,y);
- //boundary condition
- //wrap around on X
- if (x<=Xmin)
- nx=Xmax-BLOCK_WIDTH-1;
- if (x>Xmax-BLOCK_WIDTH-1)
- nx=Xmin;
- //wrap around on Y
- if (y<=Ymin)
- ny=Ymax-BLOCK_HEIGHT-1;
- if (y>Ymax-BLOCK_HEIGHT-1)
- ny=Ymin;
- //if eats target block
- if (collision(nx,ny,tx,ty)) {
- //erase target
- fill_Rectangle(tx, ty, tx+BLOCK_WIDTH, ty+BLOCK_HEIGHT, 0, 0);
- //increase snake size
- size++; ate++; //increase before
- nx = x+dx*BLOCK_WIDTH;
- ny = y+dy*BLOCK_HEIGHT;
- shift(nx,ny);
- //generate new target
- tx = rand(1, nx);
- ty = rand(0, ny);
- }
- //update pos
- x = nx;
- y = ny;
- if (ate > GOAL) {
- ate = 0;
- LCD_clear();
- game_state = end_game;
- } else
- game_state = game_background;
- break;
- case end_game: //end_game code here
- printS_5x7(1, 25, " Good Job !");
- printS_5x7(1, 32, "press any key to replay!");
- for (i=0;i<2;i++)
- CLK_SysTickDelay(SYSTICK_DLAY_us);
- while(key_pressed==0)
- key_pressed = KeyPadScanning();
- key_pressed=0;
- LCD_clear();
- game_state = welcome_screen;
- break;
- default:
- break;
- }
- }
- }
- // i 0 1 2 3 4
- // arr[i] 2 3 4 5 6
- // shifted ? 2 3 4 5 (6)
- void shift(uint8_t x, uint8_t y) {
- uint8_t i;
- for(i=1; i<GOAL; i++)
- coords[i] = coords[i-1];
- coords[0].x = x;
- coords[0].y = y;
- }
- void addLast(uint8_t x, uint8_t y) {
- if (size+1 < GOAL) {
- coords[size+1].x = x;
- coords[size+1].y = y;
- }
- }
- // Uses bounding boxes collision detection algorithm
- uint8_t collision(uint8_t x, uint8_t y, uint8_t tx, uint8_t ty) {
- //should these be eval'd with |abs| ?
- return ((x+BLOCK_WIDTH >= tx) && // tx-x <= BW <=> x+BW >= tx
- (x <= tx+BLOCK_WIDTH) &&
- (y+BLOCK_HEIGHT >= ty) &&
- (y <= ty+BLOCK_HEIGHT));
- }
- uint8_t rand(uint8_t axis, uint8_t current) {
- if (axis) //default is x
- return (current + 4*BLOCK_WIDTH) % (Xmax - BLOCK_WIDTH); //stay far from borders cause collision fails ?
- else
- return (current + 2*BLOCK_HEIGHT) % (Ymax - BLOCK_HEIGHT);
- }
- //------------------------------------------------------------------------------------------------------------------------------------
- // Functions definition
- //------------------------------------------------------------------------------------------------------------------------------------
- void LCD_start(void)
- {
- LCD_command(0xE2); // Set system reset
- LCD_command(0xA1); // Set Frame rate 100 fps
- LCD_command(0xEB); // Set LCD bias ratio E8~EB for 6~9 (min~max)
- LCD_command(0x81); // Set V BIAS potentiometer
- LCD_command(0xA0); // Set V BIAS potentiometer: A0 ()
- LCD_command(0xC0);
- LCD_command(0xAF); // Set Display Enable
- }
- void LCD_command(unsigned char temp)
- {
- SPI3->SSR |= 1ul << 0;
- SPI3->TX[0] = temp;
- SPI3->CNTRL |= 1ul << 0;
- while(SPI3->CNTRL & (1ul << 0));
- SPI3->SSR &= ~(1ul << 0);
- }
- void LCD_data(unsigned char temp)
- {
- SPI3->SSR |= 1ul << 0;
- SPI3->TX[0] = 0x0100+temp;
- SPI3->CNTRL |= 1ul << 0;
- while(SPI3->CNTRL & (1ul << 0));
- SPI3->SSR &= ~(1ul << 0);
- }
- void LCD_clear(void)
- {
- int16_t i;
- LCD_SetAddress(0x0, 0x0);
- for (i = 0; i < 132 *8; i++)
- {
- LCD_data(0x00);
- }
- }
- void LCD_SetAddress(uint8_t PageAddr, uint8_t ColumnAddr) {
- LCD_command(0xB0 | PageAddr);
- LCD_command(0x10 | (ColumnAddr>>4)&0xF);
- LCD_command(0x00 | (ColumnAddr & 0xF)); }
- void KeyPadEnable(void){
- GPIO_SetMode(PA, BIT0, GPIO_MODE_QUASI);
- GPIO_SetMode(PA, BIT1, GPIO_MODE_QUASI);
- GPIO_SetMode(PA, BIT2, GPIO_MODE_QUASI);
- GPIO_SetMode(PA, BIT3, GPIO_MODE_QUASI);
- GPIO_SetMode(PA, BIT4, GPIO_MODE_QUASI);
- GPIO_SetMode(PA, BIT5, GPIO_MODE_QUASI);
- }
- uint8_t KeyPadScanning(void){
- PA0=1; PA1=1; PA2=0; PA3=1; PA4=1; PA5=1;
- if (PA3==0) return 1;
- if (PA4==0) return 4;
- if (PA5==0) return 7;
- PA0=1; PA1=0; PA2=1; PA3=1; PA4=1; PA5=1;
- if (PA3==0) return 2;
- if (PA4==0) return 5;
- if (PA5==0) return 8;
- PA0=0; PA1=1; PA2=1; PA3=1; PA4=1; PA5=1;
- if (PA3==0) return 3;
- if (PA4==0) return 6;
- if (PA5==0) return 9;
- return 0;
- }
- void System_Config (void){
- SYS_UnlockReg(); // Unlock protected registers
- // Enable clock sources
- //LXT - External Low frequency Crystal 32 kHz
- CLK->PWRCON |= (0x01ul << 1);
- while(!(CLK->CLKSTATUS & (1ul << 1)));
- CLK->PWRCON |= (0x01ul << 0);
- while(!(CLK->CLKSTATUS & (1ul << 0)));
- //PLL configuration starts
- CLK->PLLCON &= ~(1ul<<19); //0: PLL input is HXT
- CLK->PLLCON &= ~(1ul<<16); //PLL in normal mode
- CLK->PLLCON &= (~(0x01FFul << 0));
- CLK->PLLCON |= 48;
- CLK->PLLCON &= ~(1ul<<18); //0: enable PLLOUT
- while(!(CLK->CLKSTATUS & (0x01ul << 2)));
- //PLL configuration ends
- //clock source selection
- CLK->CLKSEL0 &= (~(0x07ul << 0));
- CLK->CLKSEL0 |= (0x02ul << 0);
- //clock frequency division
- CLK->CLKDIV &= (~0x0Ful << 0);
- //enable clock of SPI3
- CLK->APBCLK |= 1ul << 15;
- SYS_LockReg(); // Lock protected registers
- }
- void SPI3_Config (void){
- SYS->GPD_MFP |= 1ul << 11; //1: PD11 is configured for alternative function
- SYS->GPD_MFP |= 1ul << 9; //1: PD9 is configured for alternative function
- SYS->GPD_MFP |= 1ul << 8; //1: PD8 is configured for alternative function
- SPI3->CNTRL &= ~(1ul << 23); //0: disable variable clock feature
- SPI3->CNTRL &= ~(1ul << 22); //0: disable two bits transfer mode
- SPI3->CNTRL &= ~(1ul << 18); //0: select Master mode
- SPI3->CNTRL &= ~(1ul << 17); //0: disable SPI interrupt
- SPI3->CNTRL |= 1ul << 11; //1: SPI clock idle high
- SPI3->CNTRL &= ~(1ul << 10); //0: MSB is sent first
- SPI3->CNTRL &= ~(3ul << 8); //00: one transmit/receive word will be executed in one data transfer
- SPI3->CNTRL &= ~(31ul << 3); //Transmit/Receive bit length
- SPI3->CNTRL |= 9ul << 3; //9: 9 bits transmitted/received per data transfer
- SPI3->CNTRL |= (1ul << 2); //1: Transmit at negative edge of SPI CLK
- SPI3->DIVIDER = 0; // SPI clock divider. SPI clock = HCLK / ((DIVIDER+1)*2). HCLK = 50 MHz
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement