EJERCICIO SIMON: Axel Oropeza Matias Rodriguez

Dependencies:   mbed tsi_sensor

main.cpp

Committer:
matirodriguez
Date:
2019-06-08
Revision:
2:90667b428ce6
Parent:
1:f6ea213ed382

File content as of revision 2:90667b428ce6:

#include "mbed.h"
#include "tsi_sensor.h"

#define ELEC0 9
#define ELEC1 10

/*  Defino esas palabras que luego usaré para
lo que se pulsa en el TSI como numeros usando la funcion
"enum{}"
*/
enum {NADA,
      ROJO,
      VERDE,
      AZUL
     };
/*  Defino los nombres de los estados como
numeros enteros con la funcion "enum{}"
*/

//Maquina "MAQ_SECUENCIA()"
enum {ESPERO_USUARIO,
      MUESTRO_SECUENCIA,
      COMPARO_SECUENCIA
     };
     
//Maquina "MAQ_MUESTREO()"
enum {ESPERO_HAB,
      MUESTRO,
      APAGO
     };
     
//Maquina "MAQ_COMPARO()"
enum {ESPERAR_HAB,
      ESPERAR_USUARIO,
      COMPARO
     };
     
#define ERROR 15
#define CORRECTO 24

TSIAnalogSlider tsi(ELEC0, ELEC1, 40);

// Prototipos de funciones de maquinas de estados
void MAQ_SECUENCIA();
void MAQ_MUESTREO();
void MAQ_COMPARO();

void MAQ_lecturaTSI();

void LEER_TSI();    //Prototipo funcion de lectura del TSI
void LED_1SEG();    //Prototipo funcion para prender y apagar led cada 1 segundo

void pulsacion_TSI();   //Prototipo funcion para leer 1 solo valor del TSI cada 2.5mseg

void genero_secuencia(); // Funcion que utilizo para generar la secuencia aleatoria.

void apago_leds();

void cambio_estado();

//Variables que indican el estado de las maquinas (empiezo en estado de reset)
int estado_maq_sec = ESPERO_USUARIO;
int estado_maq_mues = ESPERO_HAB;
int estado_maq_comp = ESPERAR_HAB;

int estado_maq_tsi = NADA;

//Variables que habilitan maquinas de estados
int hab_mostrar = 0;
int hab_comparo = 0;

//Variables que me indican el fin de una maquina de estados
int fin_mostrar = 0;
int fin_comparo = 0;

//Variables que acumulan datos
int color[25]; //Esta variable contendrá toda la secuencia aleatoria de 24 valores (no voy a usar el valor 0).
int nivel = 0;  //Esta variable me indica el nivel actual
int tiempo_muestreo = 0;    // Variable para contar el 1 segundo para el encendido y apagado de leds
int var_pulsacion = 25;     // Variable para contar los 2.5mseg de la funcion pulsacion_TSI()

int color_teclado = NADA;   // Variable que contiene el valor del TSI en todo momento
int ingreso = NADA;         // Variable que contiene el color presionado en el TSI, que se lee y luego es borrado

Ticker lectura; // Ticker lectura del TSI
Ticker temporizador;    // Ticker para contar 1 segundo en los leds
Ticker pulsacion;   // Ticker para usar la funcion pulsacion_TSI()

Timeout apago;
Timeout estado; // Una pequeña demora que agrego entre que comparo y muestro los niveles del juego

// DEFINO SALIDAS
DigitalOut ledrojo(LED_RED);
DigitalOut ledverde(LED_GREEN);
DigitalOut ledazul(LED_BLUE);

AnalogIn noise(PTB0);   // Entrada que usaré para generar la secuencia aleatoria con el ruido que me genere

int main(void)
{

// Uno las funciones con el ticker correspondiente
    lectura.attach(&LEER_TSI,0.1);
    pulsacion.attach(&pulsacion_TSI,0.001);
    temporizador.attach(&LED_1SEG,0.01);

// Apago los leds al iniciar
    ledrojo = 1;
    ledverde= 1;
    ledazul = 1;

    while (true) {

// Constantemente uso las maquinas de estados

        MAQ_lecturaTSI();

        MAQ_SECUENCIA();

        MAQ_MUESTREO();

        MAQ_COMPARO();

    }
}

void apago_leds(){
    ledrojo=1;
    ledverde=1;
    ledazul=1;    
}

void LEER_TSI()
{
    float auxiliar = 0;
    auxiliar = tsi.readPercentage();    //Guardo de manera auxiliar el valor entre 0 y 1 del TSI

// Asocio el valor del tsi numerico con un color, dividiendo en 4 valores posibles (0, <0.33, <0.66, <1)

    if(auxiliar == 0) {
        color_teclado = NADA;
    }

    if((auxiliar > 0.05)&&(auxiliar < 0.30)) {
        color_teclado = ROJO;
    }

    if((auxiliar >= 0.38)&&(auxiliar <= 0.60)) {
        color_teclado = VERDE;
    }

    if((auxiliar > 0.68)&&(auxiliar <= 1)) {
        color_teclado = AZUL;
    }
}

void pulsacion_TSI()
{
    if(var_pulsacion > 0) {
        var_pulsacion--;
    }
}

void MAQ_lecturaTSI()
{
    if(var_pulsacion < 1) { // Si se llegaron a los 2.5ms:
        var_pulsacion = 25; // Vuelvo a establecer 2.5ms para el proximo ciclo
        switch(estado_maq_tsi) {
            case NADA:
                ingreso = NADA; // La variable ingreso, salvo en los casos especificos, siempre se encontrará en NADA

                // En vez de usar cadenas de if en las transiciones, utilizo un switch

                switch(color_teclado) {
                    case ROJO:
                        estado_maq_tsi = ROJO;
                        ingreso = ROJO;
                        break;
                    case VERDE:
                        estado_maq_tsi = VERDE;
                        ingreso = VERDE;
                        break;
                    case AZUL:
                        estado_maq_tsi = AZUL;
                        ingreso = AZUL;
                        break;
                }
                break;

            case ROJO:
                switch(color_teclado) {
                    case NADA:
                        estado_maq_tsi = NADA;
                        break;
                    case VERDE:
                        estado_maq_tsi = VERDE;
                        ingreso = VERDE;
                        break;
                    case AZUL:
                        estado_maq_tsi = AZUL;
                        ingreso = AZUL;
                        break;
                }
                break;

            case VERDE:
                switch(color_teclado) {
                    case NADA:
                        estado_maq_tsi = NADA;
                        break;
                    case ROJO:
                        estado_maq_tsi = ROJO;
                        ingreso = ROJO;
                        break;
                    case AZUL:
                        estado_maq_tsi = AZUL;
                        ingreso = AZUL;
                        break;
                }
                break;

            case AZUL:
                switch(color_teclado) {
                    case NADA:
                        estado_maq_tsi = NADA;
                        break;
                    case ROJO:
                        estado_maq_tsi = ROJO;
                        ingreso = ROJO;
                        break;
                    case VERDE:
                        estado_maq_tsi = VERDE;
                        ingreso = VERDE;
                        break;
                }
                break;
        }
    }
}

void LED_1SEG()
{
    if(tiempo_muestreo >= 0) {
        tiempo_muestreo--;
    }
}


void MAQ_SECUENCIA()
{

    switch(estado_maq_sec) {    //El switch variará entre los distintos estados de mi maquina (los numeros correspondientes se encuentran en el "enum{}" al inicio del codigo)

        case ESPERO_USUARIO:
            if(ingreso != NADA) {   // Si se presiona algo:
                genero_secuencia(); // Genero la secuencia
                nivel++;    // Sumo 1 a "nivel" asi comienzo por el nivel 1
                hab_mostrar = 1;    // Habilito la maquina de estados que muestra los colores
                estado_maq_sec = MUESTRO_SECUENCIA; // Cambio de estado
                ingreso = NADA; // Reseteo la variable que contenia el color presionado
                ledrojo=1;
                ledazul=1;
                ledverde=1;
            }
            break;

        case MUESTRO_SECUENCIA:

            if(fin_mostrar == 1) {  // Si se terminó la maquina de estados que muestra:
                fin_mostrar = 0;    // Vacio la variable que me lo indicó,
                estado_maq_sec = COMPARO_SECUENCIA; // cambio de estado y
                hab_comparo = 1;    // habilito la maquina que compara
            }

            break;

        case COMPARO_SECUENCIA:

            if(fin_comparo == CORRECTO) {   // Si el usuario no se equivocó:
                if(nivel == 25) {   // y se llego al maximo de niveles:
                    fin_comparo = 0;    // Vacio la variable
                    estado_maq_sec = ESPERO_USUARIO;    // Cambio al estado de inicio
                    nivel = 0;  // y reseteo todos los niveles
                    ledverde=0; //Prendo leds para indicar que gané
                    ledazul=0;
                }
                if(nivel < 25) {    // Si en cambio faltan niveles:
                    fin_comparo = 0;    // Vacio la variable
                    estado_maq_sec = MUESTRO_SECUENCIA; // Vuelvo al estado de mostrar
                    hab_mostrar = 1;    // Habilito esa maquina
                    nivel++;    // Y subo 1 nivel
                }
            }
            if(fin_comparo == ERROR) {
                fin_comparo = 0;
                estado_maq_sec = ESPERO_USUARIO;
                nivel = 0;
                ledrojo=0;  // Prendo el leds para indicar que se perdió
                ledazul = 0;
            }
            break;
    }
}

void MAQ_MUESTREO()
{

    static int nivel_mostrado;  // Variable que voy a tener para saber que nivel estoy mostrando en los leds ahora

    switch(estado_maq_mues) {   // Uso un switch para variar entre los estados de la maquina

        case ESPERO_HAB:

            nivel_mostrado = 1; // El primer nivel que muestro es 1, asi que reseteo esta variable cada vez que paso por este estado

            if(hab_mostrar == 1) {  // Cuando recibo la habilitacion de la otra maquina de estados:

                estado_maq_mues = MUESTRO;  // Cambio de estado y
                tiempo_muestreo = 100;  // Establezco el tiempo en 1 seg (0.01seg * 100 = 1seg)
                hab_mostrar = 0;

            }
            break;

        case MUESTRO:

            switch(color[nivel_mostrado]) { // Muestro el color correspondiente al primer nivel, y voy cambiando cada 2 segundos
                case ROJO:
                    ledrojo = 0;
                    ledverde=1;
                    ledazul=1;
                    break;

                case VERDE:
                    ledverde = 0;
                    ledazul=1;
                    ledrojo=1;
                    break;

                case AZUL:
                    ledazul = 0;
                    ledrojo=1;
                    ledverde=1;
                    break;
            }

            if(tiempo_muestreo == 0) {  // Si pasó 1 segundo, reseteo el tiempo y cambio de estado
                tiempo_muestreo = 100;  // Establezco el tiempo en 1 segundo otra vez
                estado_maq_mues = APAGO;    // Cambio de estado
            }
            break;

        case APAGO:

            switch(color[nivel_mostrado]) { // Ahora voy a apagar el led correspondiente al nivel que se esta mostrando.
                case ROJO:
                    ledrojo = 1;
                    break;
                case VERDE:
                    ledverde = 1;
                    break;
                case AZUL:
                    ledazul = 1;
                    break;
            }
            if(tiempo_muestreo == 0) {  // Si paso el tiempo
                if(nivel_mostrado == nivel) {   // Y no faltan niveles
                    nivel_mostrado = 1; // Reseteo el nivel a mostrar
                    estado_maq_mues = ESPERO_HAB;   // Vuelvo a esperar la habilitacion
                    fin_mostrar = 1; // Y marco que termino la maquina de estados
                } else {
                    estado_maq_mues = MUESTRO;  // Si en cambio faltan niveles, vuelvo a mostrar
                    nivel_mostrado++;   // Y muestro el siguiente
                    tiempo_muestreo = 100;  // Reseteo el tiempo (1 segundo)
                }
            }
            break;
    }
}

void MAQ_COMPARO()
{


    static int nivel_comparado; // Variable que voy a usar para comparar todos los niveles sucesivamente, con lo que se vaya ingresando en el TSI
    static int obtenido = NADA; // En esta variable voy a guardar lo que se ingrese para poder resetear la variable que me lo indica y no perder la informacion

    switch(estado_maq_comp) {
        case ESPERAR_HAB:

            nivel_comparado = 1; // Establezco en este estado el primer nivel que se va a comparar (el 1)

            if(hab_comparo == 1) {  // Si recibí habilitacion desde la otra maquina, cambio de estado
                estado_maq_comp = ESPERAR_USUARIO;
                hab_comparo = 0;
            }

            break;

        case ESPERAR_USUARIO:

            if(ingreso != NADA) { // Si se ingresa algo en el TSI, lo guardo en la variable "obtenido"
                obtenido = ingreso;
                ingreso = NADA; // Reseteo la variable que guarda el valor del TSI
                estado_maq_comp = COMPARO;
            }

            break;

        case COMPARO:   //Estado donde comparo el valor que se ingresó con el valor que corresponde

            if(obtenido == color[nivel_comparado]) {    // Si el resultado es igual a lo que deberia:

                // Imprimo en pantalla el valor que se ingresó para comprobar
                switch(color[nivel_comparado]) {
                    case ROJO:
                        printf("Rojo\n");
                        ledrojo=0;
                        break;
                    case VERDE:
                        printf("Verde\n");
                        ledverde=0;
                        break;
                    case AZUL:
                        printf("Azul\n");
                        ledazul=0;
                        break;
                }
                apago.attach(&apago_leds,0.5);
                obtenido = NADA;    // Reseteo la variable
                if(nivel_comparado <= nivel) {  // Si quedan niveles
                    
                    estado_maq_comp = ESPERAR_USUARIO; //Vuelvo al estado de esperar que el usuario ingrese algo y
                    nivel_comparado++;  // Paso al siguiente nivel.
                }
                if(nivel_comparado > nivel) { // Si no quedan niveles
                    estado_maq_comp = ESPERAR_HAB;  // Reseteo la maquina
                     estado.attach(&cambio_estado,1); // Indico que todo lo ingresado hasta este nivel es correcto
                }
            } else {    // Si, en cambio, se ingreso algo incorrecto
                estado_maq_comp = ESPERAR_HAB;  // Reseteo la maquina
                fin_comparo = ERROR;    // Marco error
                //Imprimo en pantalla que hubo error para comprobar
                printf("ERROR\n");
                
                // Imprimo en pantalla el valor que se ingresó para comprobar
                switch(color[nivel_comparado]) {
                    case ROJO:
                        printf("Rojo\n");
                        break;
                    case VERDE:

                        printf("Verde\n");
                        break;
                    case AZUL:
                        printf("Azul\n");
                        break;


                }

            }
            break;
    }
}

void genero_secuencia()
{
    int auxiliar;

    srand(int (noise * 10000)); // Cambio la semilla de la funcion rand usando un valor de ruido en una entrada analogica al aire

    for(int i = 1; i <=25 ; i++) {  // Creo un for para recorren las 25 posiciones de memoria del vector "color[]" (el valor 0 no lo utilizo)


        auxiliar = rand();  //Genero un valor aleatorio y lo guardo en mi variable auxiliar

        // Dependiendo de cuanto resto me de al dividir por 3, asignare ese valor aleatorio con un color
        if((auxiliar % 3) == 0) {
            color[i] = ROJO;
        }

        if((auxiliar % 3 )== 1) {
            color[i] = VERDE;
        }

        if((auxiliar % 3 )== 2) {
            color[i] = AZUL;
        }
        switch(color[i]) {
            case ROJO:
                printf("%i ROJO;",i);
                break;
            case VERDE:
                printf("%i VERDE;",i);
                break;
            case AZUL:
                printf("%i AZUL;",i);
                break;
        }
    }
    printf("\n");
}

void cambio_estado(){
    fin_comparo = CORRECTO;
}