/* 
 * File:   main.h
 * Author: Christian Mares
 * 
 * Created on 16 de febrero de 2018, 14:07 
 */

#ifndef MAIN_H
#define MAIN_H

#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdint.h>
#include <stdbool.h>
#include <float.h>

#include "MCC_Generated/mcc.h"

#include "IO.h"
#include "LCD.h"
#include "UART.h"
#include "PWM.h"
#include "tmr4.h"
#include "tmr5.h"

#include "MM7150_SensorModule.h"
#include "Display.h"
#include "Ruedas.h"
#include "menu_LCD.h"
#include "velocimetro.h"
#include "PID.h"
#include "to_do_list.h"
#include "locomotion.h"

#include "string_ops.h"


// Data output
//#define BL_PID_DATA
//#define BS_PID_DATA
//#define SP_PID_DATA
//#define INERTIA_DATA
#define OSCIM_DATA
//#define VELOCIMETRO_DATA
//#define SENSORFUSION_DATA


/** Constantes **/
#define PI 3.141592653589     

//Configuracion de arranque
#define DIRMOD false//true         //1-->Modo Directo.             0-->Modo Ventana
#define OUTPUT true//false        //1-->No sacar output por UART. 0-->Scar Output
#define BL_PIDNBL false     //1-->Balance_PID activado.     0-->PID desactivado
#define SP_PIDNBL false     //1-->Speed_PID activado.       0-->PID desactivado


//Para la funcion delay
#define SEGUNDOS 1000
#define DECIMAS   100
#define CENTESIMAS 10

//Delays del bucle principal. Su duracion se determina segun el periodo el T4
#if(T4_Period == PR_1250)
 #define DELAY_1     19
 #define DELAY_2     19
 #define DELAY_4     9
 #define OLED_DELAY  1000
#elif(T4_Period == PR_2500)
 #define DELAY_1     9
 #define DELAY_2     9
 #define OLED_DELAY  500
#elif(T4_Period == PR_25000)
 #define DELAY_1     9
 #define DELAY_2     0 
 #define OLED_DELAY  50
#endif
#define DELAY_3     1

int main();

extern char c[40]; //String para escribir ensajes con proposito general
extern char* c_max, c_lp;

extern double cpu;
extern unsigned int cpu_free_cycles;

typedef struct type_M_CF{
    uint8_t IO:1;            // Ha habido cambios en IO
    uint8_t UART:1;          // ||   ||     ||    en UART
    uint8_t PWM:1;           // ||   ||     ||    en PWM
    uint8_t RUEDAS:1;        // ||   ||     ||    en RUEDAS
    uint8_t SENSOR_cf:1;        // ||   ||     ||    en SENSOR_cf
    uint8_t PID:1;           // ||   ||     ||    en PID
    uint8_t LOCOMO:1;        // ||   ||     ||    en LOCOMO
}M_CF;
extern volatile M_CF M;
typedef struct type_IO_CF{
    uint8_t GEN:1;                  //Bit generico, util para notificar un cambio en un modulo, sin referirse a ninguna funcion
    uint8_t S3:1;                   // Pulsador S3
    uint8_t S6:1;                   // Pulsador S6
    uint8_t S5:1;                   // Pulsador S5
    uint8_t S4:1;                   // Pulsador S4
    uint8_t GainChange:1;           // Se ha cambiado la ganancia proporcional, integral o derivada.
}IO_CF_t;
extern volatile IO_CF_t io_cf;
extern volatile char* IO_cf;
typedef struct type_UART_CF{        
    uint8_t GEN:1;                  //Bit generico.
    uint8_t WIN:1;                  //(WINDOW) Se levanta cuando hay un cambio en la ventana del display.
    uint8_t CMD:1;                  //(COMMAND) Se levanta cuando hay comando pendientes de ejecutar.
    uint8_t CMDBUFFUL:1;            //(CMD Buffer if Full) Se levanta cuando DMC_Buffer esta lleno.
}UART_CF_t;                           
extern volatile UART_CF_t uart_cf;     
extern volatile char* UART_cf;  
typedef struct type_PWM_CF{         
    uint8_t GEN:1;                  //Bit generico.
    uint8_t DCC:1;                  //(Duty Cicle Change) Se levanta cuando hay un cambio en el duty cicle de OC1,OC2,OC3,OC4.
}PWM_CF_t;                            
extern volatile PWM_CF_t pwm_cf;   
extern volatile char* PWM_cf;      
typedef struct type_RUEDAS_CF{      
    uint8_t GEN:1;                  //Bit generico.
    uint8_t P100:1;                 //Porcentaje del Duty cicle cambiado para rueda Dcha y/o izda.
}RUEDAS_CF_t;                         
extern volatile RUEDAS_CF_t ruedas_cf; 
extern volatile char* RUEDAS_cf;  
typedef struct type_SENSOR_CF{      
    uint8_t GEN:1;                  //Bit generico.
    uint8_t INCL:1;                 //Nuevo dato del sensor de inclinacion.
    uint8_t BIAS:1;                 //Muestra del GYRO.
}SENSOR_CF_t;                         
extern volatile SENSOR_CF_t sensor_cf; 
extern volatile char* SENSOR_cf;  
typedef struct type_PID_CF{         
    uint8_t GEN:1;                  //Bit generico.
    uint8_t TUNING:1;              //.
    uint8_t B_TUNING:1;            //.
    uint8_t S_TUNING:1;            //.
    uint8_t BALANCE:1;              //.            
    uint8_t SPEED:1;                //.
}PID_CF_t;                            
extern volatile PID_CF_t pid_cf;  
extern volatile char* PID_cf;       
typedef struct type_LOCOMO_CF{      
    uint8_t GEN:1;                  //Bit generico.
    uint8_t DISTGOAL:1;                 //Distancia propuesta alcanzada.
}LOCOMO_CF_t;
extern volatile LOCOMO_CF_t locomo_cf;
extern volatile char* LOCOMO_cf;

#define IO_cf          (IO_cf)
    #define IO_GEN          (io_cf.GEN)
    #define IO_S3           (io_cf.S3)
    #define IO_S6           (io_cf.S6)
    #define IO_S5           (io_cf.S5)
    #define IO_S4           (io_cf.S4)
    #define IO_GainChange   (io_cf.GainChange)
#define UART_cf         (UART_cf)
    #define UART_WIN        uart_cf.WIN
    #define UART_CMD        uart_cf.CMD
    #define UART_CMDBUFFUL  uart_cf.CMDBUFFUL
#define PWM_cf          (PWM_cf)
    #define PWM_DCC         pwm_cf.DCC
#define RUEDAS_cf       (RUEDAS_cf)
    #define RUEDAS_P100     ruedas_cf.P100
#define SENSOR_cf       (SENSOR_cf)
    #define SENSOR_INCL     sensor_cf.INCL
    #define SENSOR_BIAS     sensor_cf.BIAS
#define PID_cf          (PID_cf)
    #define PID_TUNING     pid_cf.TUNING
    #define PID_B_TUNING   pid_cf.B_TUNING
    #define PID_S_TUNING   pid_cf.S_TUNING
    #define PID_BALANCE     pid_cf.BALANCE
//    #define PID_SP          (pid_cf & PID_SP_b)
    #define PID_SPEED       pid_cf.SPEED
#define LOCOMO_cf       (LOCOMO_cf)
    #define LOCOMO_GEN      locomo_cf.DISTGOAL

/**
  @Summary
    cromometro.
  @Description
    Espera el tiempo indicado, bloqueando y mostrando la cuenta por LCD.
  @Param
    m = minutos
    secs = segundos
    f = centesimas de segundo
*/
void cronometro(uint8_t m, uint8_t secs, uint16_t f);
/**
  @Summary
    Actualiza el estado de los leds que indican la inclincion respecto al punto 
    de equilibrio.
*/
void updateTiltLeds(void);
/**
  @Summary
    Controla el flujo del bucle principal, cuenta los ciclos de CPU libres y da
    proporciona informacion acerca de esto.
*/
void loopEndHold(void);

#endif
