#include <avr/io.h>
extern void Delay(uint8_t num);
//delays necesarios
#define short_pressed_delay 100
#define long_pressed_delay 1000
#define won_sequence_delay 250
#define lose_sequence_delay 1000
#define WFS_sequence_delay 500
#define PLS_sequence_delay 1500
#define playing_level_sequence_delay 150
//vectores de secuencias;
uint8_t DDRF_ON_OFF_LED[6] = {0x07, 0x03, 0x03, 0x06, 0x06, 0x05};
uint8_t PORTF_ON_OFF_LED[6] = {0xF8, (5<<PF0) | 0xF8, (6<<PF0) | 0xF8 , (2<<PF0) | 0xF8 , (5<<PF0) | 0xF8, (1<<PF0) | 0xF8};
uint8_t DDRF_WFS_sequence[6][5] = {{0x03, 0x03, 0x06, 0x06, 0x05},
{0x07, 0x03, 0x06, 0x06, 0x05},
{0x03, 0x07, 0x06, 0x06, 0x05},
{0x03, 0x03, 0x07, 0x06, 0x05},
{0x03, 0x03, 0x06, 0x07, 0x05},
{0x03, 0x03, 0x06, 0x06, 0x07}};
uint8_t PORTF_WFS_sequence[6][5]= {{(5<<PF0) | 0xF8, (6<<PF0) | 0xF8 , (3<<PF0) | 0xF8 , (5<<PF0) | 0xF8, (3<<PF0) | 0xF8},
{0xF8, (6<<PF0) | 0xF8 , (3<<PF0) | 0xF8 , (5<<PF0) | 0xF8, (3<<PF0) | 0xF8},
{(5<<PF0) | 0xF8, 0xF8 , (3<<PF0) | 0xF8 , (5<<PF0) | 0xF8, (3<<PF0) | 0xF8},
{(5<<PF0) | 0xF8, (6<<PF0) | 0xF8 , 0xF8 , (5<<PF0) | 0xF8, (3<<PF0) | 0xF8},
{(5<<PF0) | 0xF8, (6<<PF0) | 0xF8 , (3<<PF0) | 0xF8 , 0xF8, (3<<PF0) | 0xF8},
{(5<<PF0) | 0xF8, (6<<PF0) | 0xF8 , (3<<PF0) | 0xF8 , (5<<PF0) | 0xF8, 0xF8}};
//arreglo de botones
uint8_t buttons[5] = {
PF3,
PF4,
PF5,
PF6,
PF7
};
//enumeraciones
typedef enum eButton_state {
not_pressed=0,
undefined_pressed,
short_pressed,
long_pressed
} eButton_state;
typedef enum eButton_Id {
no_button_pressed=0,
button_1,
button_2,
button_3,
button_4,
button_5
} eButton_Id;
typedef enum eSequence_state {
S0=0,
S1,
S2,
S3,
S4,
S5,
S6
} eSequence_state;
typedef enum eLEDS_state {
LED1=0,
LED2,
LED3,
LED4,
LED5
} eLEDS_state;
typedef enum eGame_state {
restart=0,
waiting_for_start,
playing_level_sequence,
waiting_for_player,
won,
lose
} eGame_state;
typedef enum ePlayer_state {
waiting_input=0,
correct_input,
incorrect_input
} ePlayer_state;
///variables globales
uint32_t _millis=0;
uint32_t millis_coppy=0;
uint32_t millis_coppy_buttons=0;
uint8_t score;
uint8_t score_check;
uint8_t up_down=1;
uint8_t button_pressed_id=0;
eSequence_state sequence_state=S0;
eLEDS_state LEDS=LED1;
uint8_t levels[6]={0};
void initIO (void) {
DDRF=0x07;
PORTF=0xF8;
}
void playSequence (eGame_state game_state) {
switch (game_state){
case waiting_for_start:
if ((_millis - millis_coppy) >= WFS_sequence_delay) {
if (sequence_state == S5 ) {
sequence_state = S0;
millis_coppy = _millis;
}
else {
sequence_state = sequence_state + 1;
millis_coppy = _millis;
}
}
if (LEDS == LED5) {
LEDS = LED1;
}
else {
LEDS = 1 + LEDS;
}
DDRF = DDRF_WFS_sequence [sequence_state] [LEDS];
PORTF = PORTF_WFS_sequence [sequence_state] [LEDS];
break;
case playing_level_sequence:
if ((_millis - millis_coppy) >= PLS_sequence_delay ) {
sequence_state = sequence_state + 1;
millis_coppy = _millis;
}
if ((_millis - millis_coppy)>= playing_level_sequence_delay) {
DDRF = DDRF_ON_OFF_LED [levels[sequence_state]];
PORTF = PORTF_ON_OFF_LED [levels[sequence_state]];
}
else {
DDRF = 0x07;
PORTF = 0xF8;
}
break;
case waiting_for_player:
DDRF = DDRF_ON_OFF_LED [button_pressed_id];
PORTF = PORTF_ON_OFF_LED [button_pressed_id];
break;
case won:
if ( sequence_state < 6) {
if ( (_millis - millis_coppy) >= won_sequence_delay ) {
DDRF = 0x07;
PORTF = 0xF8;
DDRF = DDRF_ON_OFF_LED[LEDS+1];
PORTF = PORTF_ON_OFF_LED[LEDS+1];
if (up_down==1) {
LEDS++;
}
else {
LEDS--;
}
millis_coppy=_millis;
if ( LEDS == LED5 ) {
up_down=-1;
sequence_state = sequence_state + 1;
millis_coppy=_millis;
}
else if (LEDS == LED1){
up_down=1;
sequence_state = sequence_state + 1;
millis_coppy=_millis;
}
}
}
else if ( sequence_state < 12 ) {
if ( !(sequence_state % 2) ) {
if ( (_millis - millis_coppy) > won_sequence_delay) {
sequence_state = sequence_state + 1;
millis_coppy= _millis;
}
if ( LEDS == LED5 ) {
LEDS=LED1;
}
else {
LEDS = LEDS + 1;
}
DDRF=DDRF_ON_OFF_LED[LEDS+1];
PORTF=PORTF_ON_OFF_LED[LEDS+1];
}
else {
if ( (_millis - millis_coppy) > won_sequence_delay) {
sequence_state = sequence_state + 1;
millis_coppy = _millis;
}
DDRF= 0x07;
PORTF= 0xF8;
}
}
break;
case lose:
if ( !(sequence_state % 2) ) {
if ( _millis - millis_coppy > lose_sequence_delay) {
sequence_state = sequence_state + 1;
millis_coppy= _millis;
}
if ( LEDS == LED5 ) {
LEDS=LED1;
}
else {
LEDS = LEDS + 1;
}
DDRF=DDRF_ON_OFF_LED[LEDS+1];
PORTF=PORTF_ON_OFF_LED[LEDS+1];
}
else {
if ( _millis - millis_coppy > lose_sequence_delay) {
sequence_state = sequence_state + 1;
millis_coppy = _millis;
}
DDRF = 0x07;
PORTF = 0xF8;
}
break;
}
}
///funciones
eButton_state checkButtons (eButton_Id * detected_button, eButton_state *detected_button_state) {
if ( (* detected_button_state == long_pressed ) || (*detected_button_state == short_pressed) ) {
*detected_button = no_button_pressed;
return not_pressed;
}
//comprobamos si en PINF todos los pines de PF3 a PF7 estan en uno, si es asi, ni siquiera entra a comprobar cual.
if (((PINF >> PF4) != 0x1F) && (*detected_button == no_button_pressed)) {
//se checa cual de PF3 a PF7 esta presionado (con 0), si !( (PINn>>n) and 0000 0001 ) es 1, entra
if (!((PINF>>buttons[0]) & 1)) {
*detected_button=button_1;
millis_coppy_buttons=_millis;
return undefined_pressed;
}
else if ( !((PINF>>buttons[1]) & 1) ) {
*detected_button=button_2;
millis_coppy_buttons=_millis;
return undefined_pressed;
}
else if ( !((PINF>>buttons[2]) & 1) ) {
*detected_button=button_3;
millis_coppy_buttons=_millis;
return undefined_pressed;
}
else if ( !((PINF>>buttons[3]) & 1) ) {
*detected_button=button_4;
millis_coppy_buttons=_millis;
return undefined_pressed;
}
else if ( !((PINF>>buttons[4]) & 1) ) {
*detected_button=button_5;
millis_coppy_buttons=_millis;
return undefined_pressed;
}
}
if ( (*detected_button_state == undefined_pressed )) {
//si ya pasaron 1000 milisegundos por lo menos y pinf en el puertoq ue se detecto ya es 1 de nuevo, entonces se retorna long pressed
if ( ((_millis - millis_coppy_buttons) >= long_pressed_delay) && ((PINF >> buttons[*detected_button-1]) & 0x01)) {
return long_pressed;
}
else if ( ((_millis - millis_coppy_buttons) >= short_pressed_delay) && ((PINF >> buttons[*detected_button-1] ) & 0x01) ) {
PORTD = 1;
return short_pressed;
}
return undefined_pressed;
}
return not_pressed;
}
ePlayer_state checkPlayerInput (eButton_Id player_input) {
if ( player_input == levels[score_check] ) {
if (score_check >= score) {
return correct_input;
}
else {
score_check++;
return waiting_input;
}
}
else {
return incorrect_input;
}
}
int main (void) {
initIO();
eButton_Id button_id= no_button_pressed;
eButton_state button_state;
eGame_state game_state = restart;
ePlayer_state player_input;
button_state = not_pressed;
while (1) {
button_state=checkButtons(&button_id, &button_state);
switch (game_state){
case restart:
button_id=no_button_pressed;
button_state=not_pressed;
game_state=waiting_for_start;
player_input=waiting_input;
LEDS=LED1;
sequence_state=S0;
millis_coppy=_millis;
score=0;
score_check=0;
break;
case waiting_for_start:
if ( button_state == short_pressed ) {
game_state = playing_level_sequence;
sequence_state=S0;
LEDS=LED1;
levels[score]=_millis%5 + 1 ;
millis_coppy=_millis;
}
playSequence(game_state);
break;
case playing_level_sequence:
if (sequence_state <= score ) {
playSequence(game_state);
}
else {
game_state = waiting_for_player;
}
break;
case waiting_for_player:
button_pressed_id = button_id;
playSequence(game_state);
if ( button_state == short_pressed ) {
player_input = checkPlayerInput( button_id );
}
else if (button_state == long_pressed) {
game_state = restart;
}
if (player_input == correct_input) {
if (score < 5) {
score++;
score_check=0;
player_input = waiting_input;
levels[score]=_millis % 5 + 1;
game_state=playing_level_sequence;
sequence_state=S0;
LEDS=LED1;
millis_coppy=_millis;
}
else {
game_state=won;
millis_coppy=_millis;
sequence_state=S0;
}
}
else if ( player_input == incorrect_input ) {
game_state=lose;
millis_coppy=_millis;
sequence_state=S0;
}
break;
case won:
playSequence(game_state);
if ( sequence_state >= 12 ) {
game_state = restart;
}
break;
case lose:
playSequence(game_state);
if ( sequence_state >= 6 ) {
game_state = restart;
}
break;
}
Delay(1);
_millis++;
}
}