4 Cables con pulsadores y pull-up con 2 Displays en paralelo

Dependencies:   mbed

main.cpp

Committer:
gonzaloMS
Date:
2019-06-23
Revision:
2:e7e06ee2d6b0
Parent:
1:2f8c5940c425

File content as of revision 2:e7e06ee2d6b0:


    //Tenemos 2 displays en paralelo, y manejamos cada uno por separado a través de sus habilitaciones (con transistores al corte y saturación)

#include "mbed.h"

//Creo los Estados para las Máquinas de Estados
enum{INICIO,GENERA1,GENERA2,GENERA3,FIN,BEGINNING,CHECK1,CHECK2,CHECK3,ENDGAME,WINGAME};
//  |----------------------------------|----------------------------------------------|
//              GENERACIÓN                                  CHEQUEO
 
DigitalIn E1r(PTC12);
DigitalIn E2r(PTC13);   //  0    1    2    3          (Entradas reales/físicas)
DigitalIn E3r(PTC3);    // E1r  E2r  E3r  E4r
DigitalIn E4r(PTC4); 
DigitalIn pulsadorReset(PTE29); //Pulsador externo para hacer reset, normalmente 1
 
DigitalOut ledWin(LED2);    //Configuro Led RGB en verde para cuando ganás el juego
DigitalOut ledLost(LED1);   //Configuro Led RGB en rojo para cuando perdés el juego
 
BusOut Displays(D2,D3,D4,D5,A3,A2,A1,A0,D8); //Salidas en este orden: HAB.2 (UNIDADES) - HAB.1 (DECENAS) - G - F - E - D - C - B - A  respectivamente //
 
int E1=0;
int E2=0;   //Variables donde se van a guardar los estados de las entradas reales (Ej.: E1r en E1)
int E3=0;
int E4=0;
 
//Cada número del 0 al 9 en binario dentro de un vector, para después asignarlo al BusOut (El menos significativo acá es el más significativo del BusOut)
int numerosD[]={0b111111010,0b011000010,0b110110110,0b111100110,0b011001110,0b101101110,0b101111110,0b111000010,0b111111110,0b111001110};   //0-9 Decenas
int numerosU[]={0b111111001,0b011000001,0b110110101,0b111100101,0b011001101,0b101101101,0b101111101,0b111000001,0b111111101,0b111001101};   //0-9 Unidades

//Inicializo Tickers que ejecutan una función cada cierto tiempo en segundos
Ticker Tempo; 
Ticker Display;
Ticker parpadeoTicker;

//Funciones de cada Ticker respectivamente
void descuentaTiempo();         //Cada 1 seg le resta 1 a una variable que lleva el tiempo. Al llegar a 0, indica a través de una variable que el jugador perdió
void visualizacionDisplays();   //Genera Unidades y Decenas en base al tiempo. Maneja el BusOut que va a las patas de los displays para mostrar el tiempo  
void parpadeoFuncion();         //Hace que parpadee el led rojo cuando perdés y que parpadeen los segmentos de los displays cuando termine el juego

//Funciones de las Máquinas de estados
void generacion();  //Genera secuencia
void chequeo();     //Chequea si el estado de las entradas concuerda con la secuencia generada

//Funciones extra
void winReaccion(); //Prende el led verde si ganás (desconectas todos los cables en el orden correcto)
void reset();       //Si presionás el botón reset reinicia las variables necesarias, hace que las máquinas de estados vuelvan a empezar por su estado default y apaga los leds

//Varible que se encarga de decidir cuándo mostrar las decenas y cuándo las unidades 
int switcheo=0;

//Variables relacionadas con el tiempo que se muestra en los displays
int tiempo=60;  //Guarda el tiempo en segundos
int Decenas;    //Guarda solamente la unidad del tiempo
int Unidades;   //Guarda solamente la decena del tiempo

//Variables en las que se guarda el estado de las máquinas de estados
int secuencia;  //Para la máquina de estados de generación de secuencia
int check;      //Para la máquina de estados de chequeo de las entradas

//Variables que guardan cuántas de las entradas concuerdan con la secuencia generada
int cantIgual=0;    //Para cuando se corta un cable (1 entrada en 1, las otras 3 en 0)
int cantIgual2=0;   //Para cuando se corta el segundo cable (2 entradas en 1, las otras 2 en 0)
int cantIgual3=0;   //Para cuando se corta el tercer cable (3 entradas en 1, la otra en 0)

//Variables donde se guardan valores random que van a determinar cómo queda la secuencia
int genSec1;    //primer cable a cortar
int genSec2;    //segundo cable a cortar
int genSec3;    //tercer cable a cortar

//Vectores que guardan cada parte de la secuencia (que empieza en 0000 y termina en 1111)
int vecSec[]={0,0,0,0};     //Primer cable a cortar 
int vecSec2[]={0,0,0,0};    //Segundo cable a cortar
int vecSec3[]={0,0,0,0};    //Tercer cable a cortar
int vecSec4[]={0,0,0,0};    //Cuarto cable a cortar

//Vector que guarda el estado de las entradas para compararlo con los vectores que guardan la secuencia
int vecChq[]={0,0,0,0};

//Variable que se queda en 0 si no tiene que parpadear el display y que alterna entre 1 y 0 constantemente en el caso contrario (0 muestra el tiempo y 1 apaga el display)
int parpadeoDisplay=0;

//Variables que informan si el jugador perdió o ganó el juego
int fin=0;
int win=0;

//Variables para los "for" del programa
int i;
int y;
int k;


int main() {
    //Apago los Leds
    ledWin=1;
    ledLost=1;
    //Configuro modo de PullUp interno para las 4 entradas (los cuatro cables) y el botón de Reset
    E1r.mode(PullUp);
    E2r.mode(PullUp);
    E3r.mode(PullUp);
    E4r.mode(PullUp);
    pulsadorReset.mode(PullUp);
    //Asingo las funciones a los Tickers
    Tempo.attach(&descuentaTiempo,1);   //La funcion descuentaTiempo se va a ejecutar cada 1 segundo
    Display.attach(&visualizacionDisplays,0.005);   //La funcion visualizacionDisplays se va a ejecutar cada 5 milisegundos 
    parpadeoTicker.attach(&parpadeoFuncion,0.5);    //La funcion parpadeoFuncion se va a ejecutar cada 0,5 segundos
    while(1) {
        //Llamo a las funciones
        generacion();
        chequeo();
        winReaccion();
        reset();
        //Pongo los estados de las entradas en las variables
        E1=E1r;
        E2=E2r;
        E3=E3r;
        E4=E4r;  
    }
}
 
void reset()
{
    if(pulsadorReset==0)
    {
        //si se presiona el pulsador resetea todas las variables, los vectores (vuelven a empezar en 0000) y las máq. de estados empiezan por su estado default
        ledWin=1;
        ledLost=1;
        switcheo=0;
        cantIgual=0;
        cantIgual2=0;
        cantIgual3=0;
        vecSec[0]=0;
        vecSec[1]=0;
        vecSec[2]=0;
        vecSec[3]=0;
        vecSec2[0]=0;
        vecSec2[1]=0;
        vecSec2[2]=0;
        vecSec2[3]=0;
        vecSec3[0]=0;
        vecSec3[1]=0;
        vecSec3[2]=0;
        vecSec3[3]=0;
        vecSec4[0]=0;
        vecSec4[1]=0;
        vecSec4[2]=0;
        vecSec4[3]=0;
        vecChq[0]=0;
        vecChq[1]=0;
        vecChq[2]=0;
        vecChq[3]=0;
        parpadeoDisplay=0;
        tiempo=60;
        win=0;
        fin=0;
        secuencia=INICIO;
        check=BEGINNING;   
    }   
}
 
void winReaccion()
{
    //Si el jugador ganó, se prende el led verde y se apaga el rojo
    if(win==1)
    {
        ledWin=0;
        ledLost=1;  
    }  
}
 
void parpadeoFuncion()
{
    //Si el jugador perdió, cada 0,5 segundos que entra en la funcion cambia el estado del led rojo de 0 a 1
    if(fin==1)
    {
        ledLost=!ledLost;
    }
    //Si el jugador perdió o ganó, cada 0,5 segundos que entra en la funcion va a cambiar entre 0 y 1 la variable que indica si se tiene que mostrar el tiempo o apagar los displays
    if(fin==1 || win==1)
    {
        parpadeoDisplay=!parpadeoDisplay;   
    }   
}
 
void descuentaTiempo()
{
    //Si el juego no terminó, cada 1 segundo le resta 1 a la variable tiempo, que empieza en 60, hasta que llega a 0 e indica que el jugador perdió.
    //También cada 1 segundo muestra el estado de las variables importantes para el jugador para facilitar la depuración 
    if(fin==0 && win==0)
    {
        if(tiempo>0)
        {
            tiempo--;
        }
        else
        {
            fin=1;   
        }
        printf("A lograr: \n");
        printf("%d %d %d %d \n",*vecSec,*(vecSec+1),*(vecSec+2),*(vecSec+3));
        printf("%d %d %d %d \n",*vecSec2,*(vecSec2+1),*(vecSec2+2),*(vecSec2+3));
        printf("%d %d %d %d \n",*vecSec3,*(vecSec3+1),*(vecSec3+2),*(vecSec3+3));
        printf("%d %d %d %d \n",*vecSec4,*(vecSec4+1),*(vecSec4+2),*(vecSec4+3));
        printf("Entradas: %d %d %d %d \n", E1,E2,E3,E4);
        printf("Tiempo (en segundos): %d \n \n",tiempo);
    }
}
 
void visualizacionDisplays()
{
    //Consigo el numero perteneciente a las decenas del tiempo y lo guardo en la variable. Lo mismo para las unidades del tiempo
    Decenas=tiempo/10;
    Unidades=tiempo-((tiempo/10)*10);
    //Si no tiene que parpadear el display, va cambiar entre mostrar las decenas y unidades cada 5 milisegundos que entra a la funcion
    //Si tiene que parpadear, parpadeoDisplay cambia entre 0 y 1, mostrando el tiempo en un momento y apagando los displays en otro
    if(parpadeoDisplay==0)
    {
        //Si switcheo es par, muestra decenas, y si es impar, muestra unidades. La posicion 0 del vector corresponde al numero 0, y así hasta el 9
        if(switcheo%2==0)
        {
            Displays=numerosD[Decenas];   
        }
        else
        {
            Displays=numerosU[Unidades];
        }
    }
    else
    {
        Displays=0;   
    }
    //Como no importa el número en sí, para que no se haga muy grande para en 200 y vuelve a 0 
    if(switcheo==200)
    {
        switcheo=0;
    }
    //switcheo aumenta en 1 cada vez que se entra a la funcion
    switcheo++;             
}

void generacion(){
    switch(secuencia)
    {
        default:   
        case INICIO:
        //Se reinician las variables que se encargan de generar la secuencia
        genSec1=0;
        genSec2=0;
        genSec3=0;
        //Pasa directamente al estado GENERA1
        secuencia=GENERA1;
        break;
        
        case GENERA1:
        //Se le asigna un valor random entre 1 y 4 a la variable genSec1
        genSec1=rand()%4+1;
        //Dependiendo del valor, se le suma 1 a 1 de las 4 posiciones del vector
        if(genSec1==1)
        {
            vecSec[0]++;
        }
        else if(genSec1==2)
        {
            vecSec[1]++;
        }
        else if(genSec1==3)
        {
            vecSec[2]++;
        }
        else if(genSec1==4)
        {
            vecSec[3]++;
        }
        //Pasa directamente al estado GENERA2
        secuencia=GENERA2;
        break;
        
        case GENERA2:
        //Se le asigna un valor random entre 1 y 4 a la variable genSec2
        genSec2=rand()%4+1;
        //Se copia el contenido del vector de la primera parte de la secuencia al del vector de la segunda parte de la secuencia
        vecSec2[0]=vecSec[0];
        vecSec2[1]=vecSec[1];
        vecSec2[2]=vecSec[2];
        vecSec2[3]=vecSec[3];
        //Dependiendo del valor, se le suma 1 a 1 de las 4 posiciones del vector, excepto que la posicion a la que busca sumar 1 ya sea 1 de la generacion anterior
        //Si la posicion ya era 1 de antes, se vuelve a hacer el proceso (que incluye volver a generar un número random)
        if(genSec2==1)
        {
            if(vecSec2[0]==1)
            {
                secuencia=GENERA2; 
            }
            else
            {
                vecSec2[0]++;
            }
        }
        else if(genSec2==2)
        {
            if(vecSec2[1]==1)
            {
                secuencia=GENERA2;    
            }
            else
            {
                vecSec2[1]++;
            }
        }
        else if(genSec2==3)
        {
            if(vecSec2[2]==1)
            {
                secuencia=GENERA2;    
            }
            else
            {
                vecSec2[2]++;
            }
        }
        else if(genSec2==4)
        {
            if(vecSec2[3]==1)
            {
                secuencia=GENERA2;    
            }
            else
            {
                vecSec2[3]++;
            }
        }
        //Se busca verificar que el vector de la segunda parte de la secuencia contenga dos posiciones en 1. En ese caso, pasa al estado GENERA3
        //Sino vuelve a hacer el proceso
        if((vecSec2[0]+vecSec2[1]+vecSec2[2]+vecSec2[3]) == 2)
        {
            secuencia=GENERA3;
        }
        else
        {
            secuencia=GENERA2;   
        }
        break;
        
        case GENERA3:
        //Se le asigna un valor random entre 1 y 4 a la variable genSec3
        genSec3=rand()%4+1;
        //Se copia el contenido del vector de la segunda parte de la secuencia al del vector de la tercera parte de la secuencia
        vecSec3[0]=vecSec2[0];
        vecSec3[1]=vecSec2[1];
        vecSec3[2]=vecSec2[2];
        vecSec3[3]=vecSec2[3];
        //Dependiendo del valor, se le suma 1 a 1 de las 4 posiciones del vector, excepto que la posicion a la que busca sumar 1 ya sea 1 de la generacion anterior
        //Si la posicion ya era 1 de antes, se vuelve a hacer el proceso (que incluye volver a generar un número random)
        if(genSec3==1)
        {
            if(vecSec3[0]==1)
            {
                secuencia=GENERA3;   
            }
            else
            {
                vecSec3[0]++;
            }
        }
        else if(genSec3==2)
        {
            if(vecSec3[1]==1)
            {
                secuencia=GENERA3;   
            }
            else
            {
                vecSec3[1]++;
            }
        }
        else if(genSec3==3)
        {
            if(vecSec3[2]==1)
            {
                secuencia=GENERA3;   
            }
            else
            {
                vecSec3[2]++;
            }
        }
        else if(genSec3==4)
        {
            if(vecSec3[3]==1)
            {
                secuencia=GENERA3;   
            }
            else
            {
                vecSec3[3]++;
            }
        }
        //Se busca verificar que el vector de la tercera parte de la secuencia contenga tres posiciones en 1. En ese caso, pasa al estado FIN
        //Sino vuelve a hacer el proceso
        if((vecSec3[0]+vecSec3[1]+vecSec3[2]+vecSec3[3]) == 3)
        {
            secuencia=FIN;
        }
        else
        {
            secuencia=GENERA3;   
        }
        break;
        
        case FIN:
        //Termina con todas las posiciones en 1. Se mantiene en este estado hasta que se presione el botón de reset
        vecSec4[0]=1;
        vecSec4[1]=1;
        vecSec4[2]=1;
        vecSec4[3]=1;
        secuencia=FIN;
        break;
    }    
}
 
void chequeo(){
    switch(check)
    {
        default:
        case BEGINNING:
        //Si todas las entradas están conectadas (ningún cable sin cortar), se queda en este estado, sino cambia a CHECK1 
        if(E1!=0 || E2!=0 || E3!=0 || E4!=0)
        {
            check=CHECK1;   
        }
        else
        {
            check=BEGINNING;   
        }
        break;
        
        case CHECK1:
        //El estado de las entradas al "desconectar" una se guarda en los vectores
        vecChq[0]=E1;
        vecChq[1]=E2;
        vecChq[2]=E3;
        vecChq[3]=E4;
        //Se fija si el estado de las 4 entradas corresponde con la secuencia al desconectar solo una de las entradas
        for(i=0;i<4;i++)
        {
            if(vecSec[i]==vecChq[i])
            {
                cantIgual++;   
            }   
        }
        //Si solo se desconectó una y era la que debía ser según la secuencia, se vuelve a hacer el proceso. Si era una incorrecta, perdiste el juego
        if((vecChq[0]+vecChq[1]+vecChq[2]+vecChq[3])==1)
        {
            if(cantIgual!=4)
            {
                check=ENDGAME;
            }
            else
            {
                cantIgual=0;
                check=CHECK1;   
            }
        }
        //Si la primera que se había desconectado era la correcta y se desconecta otra más, pasa al estado CHECK2
        else if(vecChq[0]+vecChq[1]+vecChq[2]+vecChq[3])==2)
        {
            check=CHECK2;   
        }
        break;
        
        case CHECK2:
        //El estado de las entradas al desconectar la segunda se guarda en los vectores
        vecChq[0]=E1;
        vecChq[1]=E2;
        vecChq[2]=E3;
        vecChq[3]=E4;
        //Se fija si el estado de las 4 entradas corresponde con a la secuencia al desconectar la segunda entrada
        for(y=0;y<4;y++)
        {
            if(vecSec2[y]==vecChq[y])
            {
                cantIgual2++;   
            }   
        }
        //Si al desconectar la segunda entrada era la que debía ser según la secuencia, se vuelve a hacer el proceso. Si era una incorrecta, perdiste el juego
        if(vecChq[0]+vecChq[1]+vecChq[2]+vecChq[3])==2)
        {
            if(cantIgual2!=4)
            {
                check=ENDGAME;
            }
            if(cantIgual==4)
            {
                check=CHECK2;   
            }
        }
        //Si la segunda que se había desconectado era la correcta y se desconecta otra más, pasa al estado CHECK3
        else if(vecChq[0]+vecChq[1]+vecChq[2]+vecChq[3])==3)
        {
            check=CHECK3;   
        }
        break;
        
        case CHECK3:
        //El estado de las entradas al desconectar la tercera se guarda en los vectores
        vecChq[0]=E1;
        vecChq[1]=E2;
        vecChq[2]=E3;
        vecChq[3]=E4;
        //Se fija si el estado de las 4 entradas corresponde con a la secuencia al desconectar la tercera entrada
        for(k=0;k<4;k++)
        {
            if(vecSec3[k]==vecChq[k])
            {
                cantIgual3++;   
            }   
        }
        //Si al desconectar la tercera entrada era la que debía ser según la secuencia, se vuelve a hacer el proceso. Si era una incorrecta, perdiste el juego
        if(vecChq[0]+vecChq[1]+vecChq[2]+vecChq[3])==3)
        {
            if(cantIgual3!=4)
            {
                check=ENDGAME;
            }
            if(cantIgual3==4)
            {
                check=CHECK3;     
            }
        }
        //Si la tercera que se había desconectado era la correcta y se desconecta la última, evidentemente es la correcta y ganaste el juego
        else if(vecChq[0]+vecChq[1]+vecChq[2]+vecChq[3])==4)
        {
            check=WINGAME;     
        }
        break;
        
        case ENDGAME:
        //Indica que se perdió el juego
        fin=1;
        check=ENDGAME;
        break;
        
        case WINGAME:
        //Indica que se ganó el juego
        win=1;
        check=WINGAME;
        break;       
    }   
}