Comments and refactoring

This commit is contained in:
id101010
2016-01-27 14:33:51 +01:00
parent 0e7f6a5924
commit 893ec39d32
7 changed files with 721 additions and 678 deletions

View File

@@ -2,17 +2,15 @@
#include <lcd_lld.h> #include <lcd_lld.h>
#include <color.h> #include <color.h>
#include <stdio.h> #include <stdio.h>
#include "game.h" #include "game.h"
#include "io.h" #include "io.h"
void game_init(game_t* game, uint16_t ticks_per_sec) { void game_init(game_t* game, uint16_t ticks_per_sec) {
//Sysinit
//gpio init //gpio init
io_init(); io_init();
//uart init
//lcd init //lcd init
LCD_Init(); LCD_Init();
LCD_Clear(GUI_COLOR_BLACK); LCD_Clear(GUI_COLOR_BLACK);
@@ -46,50 +44,50 @@ bool game_check_line_collision(player_t* player, point_t start, point_t end, uin
switch(player->direction){ switch(player->direction){
case up: case up:
if(player->position.y > start.y && ((int16_t)player->position.y - pixels) <= start.y) { if(player->position.y > start.y && ((int16_t)player->position.y - pixels) <= start.y) {
return true; return true; // going up and hitting a line segment
} }
break; break;
case down: case down:
if(player->position.y < start.y && ((int16_t)player->position.y + pixels) >= start.y) { if(player->position.y < start.y && ((int16_t)player->position.y + pixels) >= start.y) {
return true; return true; // going down and hitting a line segment
} }
break; break;
case left: case left:
if(player->position.x > start.x && ((int16_t)player->position.x - pixels) <= start.x) { if(player->position.x > start.x && ((int16_t)player->position.x - pixels) <= start.x) {
return true; return true; // going left and hitting a line segment
} }
break; break;
case right: case right:
if(player->position.x < start.x && ((int16_t)player->position.x + pixels) >= start.x) { if(player->position.x < start.x && ((int16_t)player->position.x + pixels) >= start.x) {
return true; return true; // going right and hitting a line segment
} }
break; break;
} }
return false; return false;
} }
bool game_check_bounding_collision(game_t* game, player_t* player, uint8_t pixels){ bool game_check_boundary_collision(game_t* game, player_t* player, uint8_t pixels){
// Check bounding collision // Check boundary collision
switch(player->direction){ switch(player->direction){
case up: case up:
if((int16_t)(player->position.y) - pixels <= TFT_GAME_FIELD_TOP){ if((int16_t)(player->position.y) - pixels <= TFT_GAME_FIELD_TOP){
return true; // Collision at top return true; // Collision at top boundary
} }
break; break;
case down: case down:
if((int16_t)(player->position.y) + pixels >= (TFT_HEIGHT - TFT_GAME_FIELD_BOTTOM - 1)){ if((int16_t)(player->position.y) + pixels >= (TFT_HEIGHT - TFT_GAME_FIELD_BOTTOM - 1)){
return true; // Collision at bottom return true; // Collision at bottom boundary
} }
break; break;
case left: case left:
if((int16_t)(player->position.x) - pixels <= TFT_GAME_FIELD_LEFT){ if((int16_t)(player->position.x) - pixels <= TFT_GAME_FIELD_LEFT){
return true; // Collision at left return true; // Collision at left boundary
} }
break; break;
case right: case right:
if((int16_t)(player->position.x) + pixels >= (TFT_WIDTH - TFT_GAME_FIELD_RIGHT - 1)){ if((int16_t)(player->position.x) + pixels >= (TFT_WIDTH - TFT_GAME_FIELD_RIGHT - 1)){
return true; // Collision at right return true; // Collision at right boundary
} }
break; break;
} }
@@ -122,11 +120,10 @@ bool game_check_player_collision(game_t* game, player_t* player, uint8_t pixels)
} }
} }
// Do all collision checks! bool game_check_collision(game_t* game, player_t* player, uint8_t pixels){ // Check boundary and player collisions
bool game_check_collision(game_t* game, player_t* player, uint8_t pixels){
// Check for collisions with boundings // Check for collisions with boundarys
if(game_check_bounding_collision(game, player, pixels)){ if(game_check_boundary_collision(game, player, pixels)){
return true; return true;
} }
@@ -140,39 +137,37 @@ bool game_check_collision(game_t* game, player_t* player, uint8_t pixels){
bool game_player_update(game_t* game, player_t* player, uint8_t pixels){ bool game_player_update(game_t* game, player_t* player, uint8_t pixels){
bool directionChange = false; bool direction_change = false;
bool stateChanged = false; bool state_changed = false;
// Check for button presses // Check for button presses
if(io_button_has_edge(player->btn_left)) { if(io_button_has_edge(player->btn_left)) { // If left button is pressed
player->direction= (player->direction + (4 - 1)) % 4 ; // "decrement enum value" player->direction= (player->direction + (4 - 1)) % 4 ; // Decrement direction value (counterclockwise)
directionChange = true; direction_change = true;
} else if(io_button_has_edge(player->btn_right)) { } else if(io_button_has_edge(player->btn_right)) { // If right button is pressed
player->direction= (player->direction + 1) % 4 ; // "increment enum value" player->direction= (player->direction + 1) % 4 ; // Increment direction value (clockwise)
directionChange = true; direction_change = true;
} }
// Check if player is alive // Check if player is alive
if(player->state != alive){ if(player->state != alive){
return stateChanged; return state_changed; // If player is dead return state
} }
// Change direction // Change direction
if(directionChange) { if(direction_change) {
player_append_position(player,player->position); player_append_position(player,player->position); // Append new position if direction has changed
} }
if(pixels) { if(pixels) {
if(game_check_collision(game, player, pixels)){ // Check if a collision is about to happen
// Check if a collision is about to happen player->state = dead; // If a collision is happening kill the player
if(game_check_collision(game, player, pixels)){ state_changed = true; // return the state
player->state=dead;
stateChanged=true;
} }
point_t last_point = player->past_positions[player->num_positions-1]; point_t last_point = player->past_positions[player->num_positions-1]; // Get the players newest point
switch(player->direction) { switch(player->direction) { // Get the players moving direction and render his move
case down: case down: // render down
player->position.y+=pixels; player->position.y+=pixels;
LCD_DrawRectF( player->position.x, LCD_DrawRectF( player->position.x,
last_point.y, last_point.y,
@@ -180,7 +175,7 @@ bool game_player_update(game_t* game, player_t* player, uint8_t pixels){
player->position.y - last_point.y, player->position.y - last_point.y,
player->color); player->color);
break; break;
case left: case left: // render left
player->position.x-=pixels; player->position.x-=pixels;
LCD_DrawRectF( player->position.x, LCD_DrawRectF( player->position.x,
player->position.y, player->position.y,
@@ -188,7 +183,7 @@ bool game_player_update(game_t* game, player_t* player, uint8_t pixels){
PLAYER_WIDTH, PLAYER_WIDTH,
player->color); player->color);
break; break;
case up: case up: // render up
player->position.y-=pixels; player->position.y-=pixels;
LCD_DrawRectF( player->position.x, LCD_DrawRectF( player->position.x,
player->position.y, player->position.y,
@@ -196,7 +191,7 @@ bool game_player_update(game_t* game, player_t* player, uint8_t pixels){
last_point.y - player->position.y, last_point.y - player->position.y,
player->color); player->color);
break; break;
case right: case right: // render right
player->position.x+=pixels; player->position.x+=pixels;
LCD_DrawRectF( last_point.x, LCD_DrawRectF( last_point.x,
player->position.y, player->position.y,
@@ -206,61 +201,62 @@ bool game_player_update(game_t* game, player_t* player, uint8_t pixels){
break; break;
} }
} }
return stateChanged;
return state_changed; // return state
} }
bool game_step(game_t* game, uint64_t deltaTime) { bool game_step(game_t* game, uint64_t delta_time) { // Calculate the next game step
static long l = 0; static long l = 0;
switch(game->state) { switch(game->state) {
case prestart: case prestart: // If the game is in prestart state
//Draw welcome screen // Draw welcome screen
LCD_DrawRectF(10,10,100,50,GUI_COLOR_BLUE); LCD_DrawRectF(10,10,100,50,GUI_COLOR_BLUE);
//wait on player to press start (host) // Wait on player to press start
while(!io_button_has_edge(BTN_START)); while(!io_button_has_edge(BTN_START));
//send game start request to slave // Setup the two players
//wait on game accept response player_init(&(game->player[0]), // Player object to fill
BTN_PLAYER_1_LEFT, // Left-button
//setup BTN_PLAYER_1_RIGHT, // Right-button
player_init(&(game->player[0]),
BTN_PLAYER_1_LEFT,
BTN_PLAYER_1_RIGHT,
(point_t){ (point_t){
.x=(TFT_GAME_FIELD_START_OFFSET + TFT_GAME_FIELD_LEFT), .x=(TFT_GAME_FIELD_START_OFFSET + TFT_GAME_FIELD_LEFT), // x start coordinate
.y=(((TFT_HEIGHT - TFT_GAME_FIELD_TOP - TFT_GAME_FIELD_BOTTOM) / 2) + TFT_GAME_FIELD_TOP) .y=(((TFT_HEIGHT - TFT_GAME_FIELD_TOP - TFT_GAME_FIELD_BOTTOM) / 2) + TFT_GAME_FIELD_TOP) // y start coordinate
}, },
GUI_COLOR_BLUE, GUI_COLOR_BLUE, // color
right); right); // default moving direction
player_init(&(game->player[1]), player_init(&(game->player[1]), // Player object to fill
BTN_PLAYER_2_LEFT, BTN_PLAYER_2_LEFT, // Left-button
BTN_PLAYER_2_RIGHT, BTN_PLAYER_2_RIGHT, // Right-button
(point_t){ (point_t){
.x=(TFT_WIDTH - 1 - TFT_GAME_FIELD_RIGHT - TFT_GAME_FIELD_START_OFFSET), .x=(TFT_WIDTH - 1 - TFT_GAME_FIELD_RIGHT - TFT_GAME_FIELD_START_OFFSET), // x start coordinate
.y=(((TFT_HEIGHT - TFT_GAME_FIELD_TOP - TFT_GAME_FIELD_BOTTOM) / 2) + TFT_GAME_FIELD_TOP) .y=(((TFT_HEIGHT - TFT_GAME_FIELD_TOP - TFT_GAME_FIELD_BOTTOM) / 2) + TFT_GAME_FIELD_TOP) // y start coordinate
}, },
GUI_COLOR_RED, GUI_COLOR_RED, // color
left); left); // default moving direction
//switch state game->state = running; // Switch the game state to running
game->state = running; game->time = 0; // Reset the game time
game->time = 0;
LCD_Clear(GUI_COLOR_BLACK); LCD_Clear(GUI_COLOR_BLACK); // Clear the background
LCD_DrawRect(TFT_GAME_FIELD_LEFT,
TFT_GAME_FIELD_TOP,
(TFT_WIDTH - TFT_GAME_FIELD_LEFT - TFT_GAME_FIELD_RIGHT - 1),
(TFT_HEIGHT - TFT_GAME_FIELD_TOP - TFT_GAME_FIELD_BOTTOM - 1),
GUI_COLOR_WHITE);
LCD_SetTextColor(GUI_COLOR_WHITE); // Draw the game boundary
LCD_DisplayStringXY(TFT_GAME_HEADER_TIME_X, TFT_GAME_HEADER_TIME_Y, "Time: 0:00"); LCD_DrawRect(TFT_GAME_FIELD_LEFT, // left top x
for(int i = 0; i < PLAYER_COUNT; i++){ TFT_GAME_FIELD_TOP, // left top y
static char buf[16]; (TFT_WIDTH - TFT_GAME_FIELD_LEFT - TFT_GAME_FIELD_RIGHT - 1), // right bottom x
LCD_SetTextColor(game->player[i].color); (TFT_HEIGHT - TFT_GAME_FIELD_TOP - TFT_GAME_FIELD_BOTTOM - 1), // right bottom y
sprintf(buf, "Player%d: alive", (i+1)); GUI_COLOR_WHITE); // Color of the boundary
LCD_DisplayStringXY(TFT_GAME_HEADER_PLAYER_X+i*TFT_GAME_HEADER_PLAYER_WIDTH, TFT_GAME_HEADER_PLAYER_Y, buf);
LCD_SetTextColor(GUI_COLOR_WHITE); // Reset color to white
LCD_DisplayStringXY(TFT_GAME_HEADER_TIME_X, TFT_GAME_HEADER_TIME_Y, "Time: 0:00"); // Draw the zero-time
for(int i = 0; i < PLAYER_COUNT; i++){ // For each player print its name and its state
static char buf[16]; // Text buffer
LCD_SetTextColor(game->player[i].color); // Set the text color according to the players color
sprintf(buf, "Player%d: alive", (i+1)); // Print the state and the players name to the text buffer
LCD_DisplayStringXY(TFT_GAME_HEADER_PLAYER_X+i*TFT_GAME_HEADER_PLAYER_WIDTH, TFT_GAME_HEADER_PLAYER_Y, buf); // Print everything
} }
return true; return true;
@@ -270,47 +266,51 @@ bool game_step(game_t* game, uint64_t deltaTime) {
uint16_t ticks; uint16_t ticks;
uint16_t pixels = 0; uint16_t pixels = 0;
if(deltaTime) { if(delta_time) {
ticks = game->ticks_leftover + deltaTime; ticks = game->ticks_leftover + delta_time; // Calculate the number of past ticks
pixels = ticks / game->ticks_per_pixel; pixels = ticks / game->ticks_per_pixel; // Calculate the number of pixels moved in the calculated amount of ticks
game->ticks_leftover = ticks % game->ticks_per_pixel; game->ticks_leftover = ticks % game->ticks_per_pixel; // Calculate the number of ticks which are left
game->ticks_sum_sec += deltaTime; game->ticks_sum_sec += delta_time; // Add the delta_time to the tick sum which is used to calculate the game time
uint16_t new_seconds = game->ticks_sum_sec / game->ticks_per_sec; uint16_t new_seconds = game->ticks_sum_sec / game->ticks_per_sec; // Calculate number of seconds from past ticks
game->time += new_seconds; game->time += new_seconds; // Add the new amount of seconds to the game time
game->ticks_sum_sec = game->ticks_sum_sec % game->ticks_per_sec; game->ticks_sum_sec = game->ticks_sum_sec % game->ticks_per_sec; // Limit the tick sum used to calculate the amount of seconds
if(new_seconds > 0){ if(new_seconds > 0){ // Print the time if it got updated
static char buf[15]; static char buf[15]; // Textbufer
sprintf(buf, "Time: %d:%02d", (game->time / 60), (game->time % 60)); sprintf(buf, "Time: %d:%02d", (game->time / 60), (game->time % 60)); // Format time and paste it to the textbuffer
LCD_SetTextColor(GUI_COLOR_WHITE); LCD_SetTextColor(GUI_COLOR_WHITE); // Set the text color to white
LCD_DisplayStringXY(TFT_GAME_HEADER_TIME_X, TFT_GAME_HEADER_TIME_Y, buf); LCD_DisplayStringXY(TFT_GAME_HEADER_TIME_X, TFT_GAME_HEADER_TIME_Y, buf); // Print the time
} }
} }
bool all_players_dead = true; // Assume all players are dead ;-)
// For each player do ... // For each player do ...
bool all_players_dead = true;
for(int i = 0; i < PLAYER_COUNT; i++) { for(int i = 0; i < PLAYER_COUNT; i++) {
player_t* player = &(game->player[i]); player_t* player = &(game->player[i]); // Copy an object of the current player
if(game_player_update(game, player, pixels)) { //update player and execute if, when player state has changed
static char buf[15]; if(game_player_update(game, player, pixels)) { // Update player and execute if, when player state has changed
const char* state_text = "alive"; static char buf[15]; // Buffer to hold the text output
if(player->state==dead) { const char* state_text = "alive"; // Assume that the player is alive
if(player->state==dead) { // If the player is dead change the text
state_text="dead"; state_text="dead";
} }
sprintf(buf, "Player%d: %s ", (i+1),state_text);
LCD_SetTextColor(player->color); sprintf(buf, "Player%d: %s ", (i+1),state_text); // Format and paste the status to the buffer
LCD_DisplayStringXY(TFT_GAME_HEADER_PLAYER_X+i*TFT_GAME_HEADER_PLAYER_WIDTH, TFT_GAME_HEADER_PLAYER_Y, buf); LCD_SetTextColor(player->color); // Set the text color to the players color
LCD_DisplayStringXY(TFT_GAME_HEADER_PLAYER_X+i*TFT_GAME_HEADER_PLAYER_WIDTH, TFT_GAME_HEADER_PLAYER_Y, buf); // Print the status
} }
if(player->state!=dead) { if(player->state!=dead) { // If the current player still lives not all players are dead ...
all_players_dead=false; all_players_dead=false;
} }
} }
if(all_players_dead) { if(all_players_dead) { // End the game if all players are dead
game->state=ended; game->state=ended; // Set the state to ended
return true; return true;
} else { } else {
return false; return false;
@@ -318,9 +318,9 @@ bool game_step(game_t* game, uint64_t deltaTime) {
} }
case ended: case ended:
while(!io_button_has_edge(BTN_START)); while(!io_button_has_edge(BTN_START)); // Wait for the start button to be pressed again
LCD_Clear(GUI_COLOR_BLACK); LCD_Clear(GUI_COLOR_BLACK); // Clear the background
game->state= prestart; game->state= prestart; // Set the state to prestart
return true; return true;
} }
} }

View File

@@ -6,18 +6,23 @@
#include<stdbool.h> #include<stdbool.h>
#include"player.h" #include"player.h"
// Player definitions
#define PLAYER_COUNT 2 #define PLAYER_COUNT 2
#define PLAYER_WIDTH 0 // Don't change #define PLAYER_WIDTH 0 // Don't change
// Speed definitions
#define SPEED_SLOW 10 #define SPEED_SLOW 10
#define SPEED_FAST 1 #define SPEED_FAST 1
#define SPEED_DEFAULT (SPEED_FAST) #define SPEED_DEFAULT (SPEED_FAST)
// Button definitions
#define BTN_START 0 #define BTN_START 0
#define BTN_PLAYER_1_LEFT 3 #define BTN_PLAYER_1_LEFT 3
#define BTN_PLAYER_1_RIGHT 2 #define BTN_PLAYER_1_RIGHT 2
#define BTN_PLAYER_2_LEFT 1 #define BTN_PLAYER_2_LEFT 1
#define BTN_PLAYER_2_RIGHT 0 #define BTN_PLAYER_2_RIGHT 0
// Display definitions
#define TFT_GAME_FIELD_TOP 20 #define TFT_GAME_FIELD_TOP 20
#define TFT_GAME_FIELD_BOTTOM 5 #define TFT_GAME_FIELD_BOTTOM 5
#define TFT_GAME_FIELD_LEFT 5 #define TFT_GAME_FIELD_LEFT 5
@@ -29,40 +34,44 @@
#define TFT_GAME_HEADER_PLAYER_Y 3 #define TFT_GAME_HEADER_PLAYER_Y 3
#define TFT_GAME_HEADER_PLAYER_WIDTH 100 #define TFT_GAME_HEADER_PLAYER_WIDTH 100
/**
* @brief Game data type which contains all game data and players.
*
*/
typedef struct game_s{ typedef struct game_s{
//public section //public section ahead
uint16_t time; // seconds since game start uint16_t time; // Seconds since game start
uint16_t ticks_per_sec; uint16_t ticks_per_sec; // Number of game ticks per second
int8_t winner_id; int8_t winner_id; // Player who won the previous round
uint8_t ticks_per_pixel; uint8_t ticks_per_pixel; // Number of pixels you a player moves per tick
player_t player[PLAYER_COUNT]; player_t player[PLAYER_COUNT];
enum{ enum{ // Current state of the game
prestart, prestart,
running, running,
ended ended
} state; } state;
//private section ahead: //private section ahead
uint8_t ticks_leftover; uint8_t ticks_leftover; // Ticks left to complete a second
uint8_t ticks_sum_sec; uint8_t ticks_sum_sec; // Used to calculate the game time
} game_t; } game_t;
/** /**
@brief Initializes the game object @brief Initializes the game object
@param game @param game Game object
@param ticks_per_sec @param ticks_per_sec Number of game ticks per second
*/ */
void game_init(game_t* game, uint16_t ticks_per_sec); void game_init(game_t* game, uint16_t ticks_per_sec);
/** /**
@brief Calculates one step of the game * @brief Calculates one step of the game
@param game Game to calculate a step for *
@param deltaTime Time that passed since the last call to this method (in ticks) * @param game Game to calculate a step for
@return true if the next call to this method should be made with a delta time of zero. * @param deltaTime Time that passed since the last call to this method (in ticks)
* @return true if the next call to this method should be made with a delta time of zero.
*/ */
bool game_step(game_t* game, uint64_t deltaTime); bool game_step(game_t* game, uint64_t deltaTime);
#endif /* GAME_H */ #endif /* GAME_H */

View File

@@ -1,6 +1,6 @@
#include "io.h" #include "io.h"
//-----------Local types & functions-------------------------- // Local functions
typedef struct pin_s { typedef struct pin_s {
GPIO_TypeDef* GPIO; GPIO_TypeDef* GPIO;
uint16_t pinmask; uint16_t pinmask;
@@ -12,69 +12,64 @@ static bool pin_get(pin_t* pin);
static void pin_set(pin_t* pin, bool status); static void pin_set(pin_t* pin, bool status);
static void pin_toggle(pin_t* pin); static void pin_toggle(pin_t* pin);
// Local variables
//-------------Local Variables-------------------------
static pin_t pin_t0; static pin_t pin_t0;
static pin_t pin_t1; static pin_t pin_t1;
static pin_t pin_t2; static pin_t pin_t2;
static pin_t pin_t3; static pin_t pin_t3;
static uint8_t new = 0; static uint8_t new = 0;
static uint8_t old = 0; static uint8_t old = 0;
static volatile uint8_t edg = 0; static volatile uint8_t edg = 0;
//---------------Implementation --------------------------------
void pin_create(pin_t* pin, GPIO_TypeDef* GPIO, uint8_t pinnr, bool input) { void pin_create(pin_t* pin, GPIO_TypeDef* GPIO, uint8_t pinnr, bool input) {
GPIO_InitTypeDef gi; GPIO_InitTypeDef gi; // Create gpio init structure
GPIO_StructInit(&gi); GPIO_StructInit(&gi); // Fill gpio init structure with defaults
gi.GPIO_Pin = 1 << pinnr; gi.GPIO_Pin = 1 << pinnr; // create bitmask out of pin number
if(input) { if(input) { // If the pin is set to be an input
gi.GPIO_Mode = GPIO_Mode_IN; gi.GPIO_Mode = GPIO_Mode_IN; // Set mode to input
gi.GPIO_OType = GPIO_OType_OD; gi.GPIO_OType = GPIO_OType_OD; // Set type to open drain
gi.GPIO_PuPd = GPIO_PuPd_UP; gi.GPIO_PuPd = GPIO_PuPd_UP; // Set a pullup
} else { } else {
gi.GPIO_Mode = GPIO_Mode_OUT; gi.GPIO_Mode = GPIO_Mode_OUT; // Set mode to output
gi.GPIO_OType = GPIO_OType_PP; gi.GPIO_OType = GPIO_OType_PP; // Set type to pushpull
gi.GPIO_PuPd = GPIO_PuPd_NOPULL; gi.GPIO_PuPd = GPIO_PuPd_NOPULL; // Set no pullup
} }
GPIO_Init(GPIO,&gi); GPIO_Init(GPIO,&gi); // Update the GPIO configuration
pin->GPIO=GPIO; pin->GPIO=GPIO; // Set the gpiopin in the pin structure
pin->pinmask=0x01<<pinnr; pin->pinmask=0x01<<pinnr; // Insert the pinmask
pin->input = input; pin->input = input; // Store the input information
} }
bool pin_get(pin_t* pin) { bool pin_get(pin_t* pin) {
if(pin->input) { if(pin->input) { // If the pin is an input
return GPIO_ReadInputDataBit(pin->GPIO,pin->pinmask); return GPIO_ReadInputDataBit(pin->GPIO,pin->pinmask); // Read its value
} else { } else { // If the pin is an output
return GPIO_ReadOutputDataBit(pin->GPIO,pin->pinmask); return GPIO_ReadOutputDataBit(pin->GPIO,pin->pinmask); // Read its set value
} }
} }
void pin_set(pin_t* pin, bool status) { void pin_set(pin_t* pin, bool status) {
if(!pin->input) { if(!pin->input) { // If the pin isn't an input
GPIO_WriteBit(pin->GPIO,pin->pinmask,status); GPIO_WriteBit(pin->GPIO,pin->pinmask,status); // Set its value accordingly
} }
} }
void pin_toggle(pin_t* pin) { void pin_toggle(pin_t* pin) {
if(!pin->input) { if(!pin->input) { // If the pin isn't an input
pin_set(pin,!pin_get(pin)); pin_set(pin,!pin_get(pin)); // Toggle its value
} }
} }
void io_init(void){ void io_init(void){
//gpio init RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC,ENABLE); // Enable gpio clock source
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC,ENABLE); pin_create(&pin_t0, GPIOC, 7, true); // create pin_t0
pin_create(&pin_t0, GPIOC, 7, true); pin_create(&pin_t1, GPIOB, 15, true); // create pin_t1
pin_create(&pin_t1, GPIOB, 15, true); pin_create(&pin_t2, GPIOB, 14, true); // create pin_t2
pin_create(&pin_t2, GPIOB, 14, true); pin_create(&pin_t3, GPIOI, 0, true); // create pin_t3
pin_create(&pin_t3, GPIOI, 0, true);
} }
@@ -89,12 +84,11 @@ void io_process(void) {
} }
bool io_button_has_edge(uint8_t btnnumber) { bool io_button_has_edge(uint8_t btnnumber) {
uint8_t bm = (1 << btnnumber); // create bitmask
uint8_t bm = (1 << btnnumber); bool status = ((edg & bm) > 0); // check if button is pressed
bool status = ((edg & bm) > 0);
if(status){ if(status){
edg &= ~bm; edg &= ~bm; // clear edge bit
} }
return status; return status;

View File

@@ -5,9 +5,23 @@
#include <stm32f4xx.h> #include <stm32f4xx.h>
/**
* @brief Initialize all used GPIOs and initialize their clock source.
*/
void io_init(void); void io_init(void);
/**
* @brief Edge detection for the buttons which were initialized by io_init.
* Gets called by the systick timer.
*/
void io_process(void); void io_process(void);
/**
* @brief Edge handler which clears the edge bit to make sure a button press gets only handled once per tick.
*
* @param btnnumber Button number
* @return True if the button has a positive edge.
*/
bool io_button_has_edge(uint8_t btnnumber); bool io_button_has_edge(uint8_t btnnumber);
#endif /* IO_H */ #endif /* IO_H */

View File

@@ -4,38 +4,64 @@
#include<stdlib.h> #include<stdlib.h>
#include<stdint.h> #include<stdint.h>
#define max_positions 320 #define max_positions 320 // Maximum of points a player object is holding.
/**
* @brief Direction data type, used to specify the direction when moving.
*/
typedef enum direction_e { typedef enum direction_e {
right, right, // going right
down, down, // going down
left, left, // going left
up up // going up
} direction_t; } direction_t;
/**
* @brief Point data type which is used to store a location for the LCD.
*/
typedef struct point_s{ typedef struct point_s{
uint16_t x; uint16_t x; // x position on the display
uint8_t y; uint8_t y; // y position on the display
} point_t; } point_t;
/**
* @brief Player data type which stores all data for a single player
*/
typedef struct player_s { typedef struct player_s {
uint8_t btn_left; // players left-button
uint8_t btn_right; // players right-button
uint16_t color; // players color
uint16_t num_positions; // players number of past edges
direction_t direction; // players current moving direction
uint8_t btn_left; enum{ // players current state
uint8_t btn_right;
uint16_t color;
uint16_t num_positions;
direction_t direction;
enum{
dead, dead,
alive, alive,
} state; } state;
point_t past_positions[max_positions]; point_t past_positions[max_positions]; // used to store players waypoints
point_t position; point_t position; // current position
} player_t; } player_t;
void player_init(player_t* player, uint8_t btn_left, uint8_t btn_right, point_t pos, uint16_t color, direction_t direction); // reset all fields /**
void player_append_position(player_t* player, point_t point); // updates num_position and adds current position to the list * @brief Initialize a new player object and fill its data fields.
*
* @param player Player object
* @param btn_left Left-button for the new player
* @param btn_right Right-button for the new player
* @param pos Start position for the new player
* @param color Players color
* @param direction Players moving direction
*/
void player_init(player_t* player, uint8_t btn_left, uint8_t btn_right, point_t pos, uint16_t color, direction_t direction);
/**
* @brief Updates num_position and adds current position to the list
*
* @param player Player object
* @param point Point to add to the player object
*/
void player_append_position(player_t* player, point_t point);
#endif /* PLAYER_H */ #endif /* PLAYER_H */