#include <avr/io.h>
//#include "conf_example.h"
extern void Delay( int ); /* funcion prototype de Delay */
#define LEFT_BTN PD2
#define RIGHT_BTN PD3
#define LED_ON_DELAY 300
#define LED_OFF_DELAY 50
#define SPEED_UP 20
uint8_t btnArray[] =
{
LEFT_BTN,
RIGHT_BTN
};
enum
{
eGoingLeft = -1,
eGoingRight = 1
};
// Enumerations
typedef enum ButtonState_tag
{
eBtnUndefined = 0,
eBtnShortPressed, // if duration is lower than 999mS, its a short press
eBtnLongPressed // else if > 1000ms its a long Press
} eButtonState_t;
typedef enum PlayerInputState_tag
{
eWaiting = 0,
eCorrect,
eIncorrect
} ePlayerInputState_t;
typedef enum ButtonId_tag
{
eLeftButton = 0, // This enum must follow btnArray
eRightButton,
eMaxButtonId
} eButtonId_t;
typedef enum GameState_tag
{
eGameRestart = 0,
eWaitForStart,
eOngoingGame,
eEnd
} eGameState_t;
// Global variable
uint32_t _millis;
uint32_t wait_time;
uint32_t btn_time;
uint8_t score;
int8_t walking_value;
int8_t count;
uint8_t leds;
uint8_t step;
uint8_t wasShortPressed;
void ports(uint8_t op){
PORTB = 0; //Pone los puertos en 0
switch(op){
case 0:
PORTB = 1<<PB0;
DDRB = 3<<PB0;
break;
case 1:
PORTB = 1<<PB1;
DDRB = 3<<PB0;
break;
case 2:
PORTB = 1<<PB1;
DDRB = 3<<PB1;
break;
case 3:
PORTB = 1<<PB2;
DDRB = 3<<PB1;
break;
case 4:
PORTB = 1<<PB0;
DDRB = 1<<PB0 | 1<<PB2;
break;
case 5:
PORTB = 1<<PB2;
DDRB = 1<<PB0 | 1<<PB2;
break;
case 6:
PORTB = 1<<PB0;
DDRB = 1<<PB0 | 1<<PB3;
break;
}
}
void walking(uint8_t value){
if(value){
ports(walking_value);
}else{
if(leds != walking_value)
ports(leds);
leds++;
if(leds > 6)
leds = 0;
}
}
void show_score(){
// for (uint8_t i = 0; i < NUM_LEDS; i++){
// my_gpio_write(ledArray[i], 0);
// }
PORTB = 0;
// for (uint8_t i = 0; i < NUM_LEDS; i++){
// if (score - (2 * i + 1) > 0){
// my_gpio_write(ledArray[i], 1);
// }else if (score - (2 * i + 1) == 0){
// if (wait_time){
// wait_time++;
// my_gpio_write(ledArray[i], 1);
// if(wait_time == LED_ON_DELAY){
// down_wait_time = 1;
// wait_time = 0;
// }
// }else if(down_wait_time){
// down_wait_time++;
// my_gpio_write(ledArray[i], 0);
// if(down_wait_time == LED_OFF_DELAY){
// down_wait_time = 0;
// wait_time = 1;
// }
// }
// }
// }
}
static void initIO(void)
{
// FIXME:
// add code to initialize all IO pins for the assigment
//DDRB = 0x03; PB0 and PB1 as output
//DDRD ...
//Set LED GPIO as a push/pull output
DDRB = 0x0F;
DDRD = ~(3<<PD2);
PORTB = 0;
//PORTD = 3<<PD2;
}
void playSequence(eGameState_t gameState)
{
// FIXME:
// Playback the corresponding animation of the gameState parameter
if(gameState == eWaitForStart){
wait_time++;
if(wait_time == 500){
walking_value++;
wait_time = 0;
}
if(walking_value > 6)
walking_value = 0;
walking(0);
}
if(gameState == eOngoingGame){
wait_time++;
if(walking_value <= 0 && wait_time >= LED_ON_DELAY){
count = eGoingRight;
}
if(walking_value == 6 && wait_time >= LED_ON_DELAY){
count = eGoingLeft;
}
if(step && wait_time == 1){
wait_time+=SPEED_UP*step;
}
if(wait_time >= LED_ON_DELAY){
walking_value += count;
wait_time = 0;
if(walking_value == 6 || walking_value == 0){
step++;
}
}
walking(1);
}
if(gameState == eEnd){
show_score();
}
}
eButtonState_t checkButtons(eButtonId_t *buttonNumber)
{
// FIXME:
// Polls each button and returns the press state and the corresponding button
if (PIND & 1<<PD3)//Left btn
{
btn_time++;
*buttonNumber = eLeftButton;
}
if (PIND & 1<<PD2)//Right btn
{
btn_time++;
*buttonNumber = eRightButton;
}
if (PIND & 3<<PD2)
{
if (btn_time > 1000)
{
btn_time = 0;
return eBtnLongPressed;
}else if (btn_time > 50)
{
btn_time = 0;
wasShortPressed = 1;
return eBtnShortPressed;
}
btn_time = 0;
}
return eBtnUndefined;
}
ePlayerInputState_t checkPlayerInput(eButtonState_t buttonState, eButtonId_t buttonId)
{
// FIXME:
// Waits for player input and verifies that it is matching the pattern
if (wait_time > 280 && (walking_value == 6 || walking_value == 0) && !wasShortPressed){
return eIncorrect;
}
if (walking_value == 4 || walking_value == 2){
wasShortPressed = 0;
}
if(buttonState == eBtnShortPressed){
if(walking_value == 0 || walking_value == 1){
if(count == eGoingLeft){
if(buttonId == eRightButton)
return eCorrect;
else
return eIncorrect;
}else{
return eIncorrect;
}
}else if(walking_value == 5 || walking_value == 6){
if(count == eGoingRight){
if(buttonId == eLeftButton)
return eCorrect;
else
return eIncorrect;
}else{
return eIncorrect;
}
}else{
return eIncorrect;
}
}
return eWaiting;
}
int main(void)
{
eGameState_t currentGameState = eGameRestart;
ePlayerInputState_t playerInputState;
eButtonId_t buttonId;
eButtonState_t buttonState;
initIO();
while(1)
{
buttonState = checkButtons(&buttonId);
if (buttonState == eBtnLongPressed)
currentGameState = eGameRestart;
switch(currentGameState)
{
case eGameRestart:
//Init game variables
leds = 0;
currentGameState++;
break;
case eWaitForStart:
playSequence(eWaitForStart);
if (buttonState == eBtnShortPressed)
currentGameState++;
break;
case eOngoingGame:
playSequence(eOngoingGame);
playerInputState = checkPlayerInput(buttonState, buttonId);
if (playerInputState == eCorrect)
{
score++;
}
else if (playerInputState == eIncorrect)
{
currentGameState = eEnd;
}
break;
case eEnd:
playSequence(eEnd);
break;
}
Delay(1); //Call assembly function for a 1 millisec Delay
_millis++;
}
}