With SD Card

Dependencies:   NAVDATA RA8875 SDFileSystem VCODATA mbed

main.cpp

Committer:
gstedile
Date:
2017-05-15
Revision:
0:e40cf759ba9a
Child:
1:30b1ca228fc7

File content as of revision 0:e40cf759ba9a:


#include "mbed.h"           // v112
#include "RA8875.h"         // v102
#include "MyFont18x32.h"
#include "BPG_Arial08x08.h"
#include "BPG_Arial10x10.h"
#include "BPG_Arial20x20.h"
#include "BPG_Arial31x32.h"
#include "BPG_Arial63x63.h"

// Agrego includes para uso en la comunicacion con el gps.
#include "GPS.h"
// Agrego includes para la clase NAVDATA que maneja los datos de navegación del último período.
#include "NAVDATA.h"
// Agrego includes para la clase VCODATA que maneja los datos de navegación más recientes parametrizados por velocidad de cada período.
#include "VCODATA.h" 
// Agrego include para SD Card
#include "SDFileSystem.h"


#include <sstream>                                  //include this to use string streams
#include <string> 

const char *sd_dir="/sd/snocc";                     // Directorio de almacenamiento de datos.
const char *sd_file="/sd/snocc/sdsnocc.csv";        // Archivo csv de almacenamiento de datos. 
int poll_init=0;                                    // Testigo de inicio de recoleccion de datos.
float Counter=0;                                    //Contador de pulsos del sensor de flujo.
float LCounter=0;                                   //Consumo en litros
const int V_M=100;                                  //Velocidad Maxima
NAVDATA NAVIGATION_TABLE;                           //Objeto que maneja los datos de navegación del último período. $
VCODATA NAVIGATION_VMATRIX(NAVIGATION_TABLE, V_M);          // Objeto que maneja la matriz de datos de navegación            $
//VCODATA NAVIGATION_V_INTRP_MTRX(NAVIGATION_TABLE, V_M);   // Objeto que maneja la matriz de datos de navegación interpolados $
VCODATA NAVIGATION_V_SMOOTH_MTRX(NAVIGATION_TABLE, V_M);    // Objeto que maneja la matriz de datos de navegación promediados $            



LocalFileSystem local("local");                 // Because I want <PrintScreen>
Serial pc(USBTX, USBRX);                        // And a little feedback

RA8875 lcd(p5, p6, p7, p8, NC, "tft");          // MOSI, MISO, SCK, /ChipSelect, /reset, name
  
SDFileSystem sd(p11, p12, p13, p14, "sd");       // SD CARD: mosi, miso, sclk, cs



 
//>>>>>>>>>>>>>>>>>>  SECCION AGREGADA PROVISORIAMENTE PARA EL TOUCH PANEL <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

extern "C" void mbed_reset();


#define min(a,b) ((a<b)?a:b)
#define max(a,b) ((a>b)?a:b)

bool Intersect(rect_t rect, point_t p)
{
    if (p.x >= min(rect.p1.x, rect.p2.x) && p.x <= max(rect.p1.x, rect.p2.x)
    && p.y >= min(rect.p1.y, rect.p2.y) && p.y <= max(rect.p1.y, rect.p2.y))
        return true;
    else
        return false;
}

int GetScreenCapture(void)
{
    char fqfn[50];
    int i = 0;
    
    pc.printf("Screen Capture... ");
    for (i=1; i< 100; i++) {
        snprintf(fqfn, sizeof(fqfn), "/local/Screen%02d.bmp", i);
        FILE * fh = fopen(fqfn, "rb");
        if (!fh) {
            lcd.PrintScreen(0,0,480,272,fqfn);
            pc.printf(" as /local/Screen%02d.bmp\r\n", i);
            return i;
        } else {
            fclose(fh);     // close this and try the next
        }
    }
    return 0;
}
//>>>>>>>>>>>>>>>>>>  FIN SECCION AGREGADA PROVISORIAMENTE PARA EL TOUCH PANEL <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

 //Función para la interrupción
  
    void trigger() {                           
         Counter++;
         LCounter=Counter/2500;
         }
         
         
 /* Funcion  print_VCO_curve : Imprime la curva de consumo/milla en funcion de la velocidad a partir del vector de objetos NAV_DATA de la clase VCODATA, con lineas (printline=1) o puntos (=0)
    Parametros: Objeto VCODATA; Interpolated: 0 -> no imprime valores interpolados o promediados; 1: interpola con puntos, 2: interpola con lineas*/

    void print_VCO_curve(VCODATA &Matrix_VCO, int interpolated){    
        //lcd.puts("ENTRANDO a print_VCO_curve\r\n");  // DEBUG
        float s; // Consumo
        int y,x;
        int VCO= Matrix_VCO.get_VCO();   
        int y_offset=250;               //Para que imprima de abajo hacia arriba.
        int y_text_offset=15;           //Para cooregir diferencia de impresion entre caracter y linea.
        int x_offset=30;                //Posicionamiento en x
        int y_i=y_offset;               //Punto origen y
        int x_i=x_offset;               //Punto origen x
        int x_scale=4;                  // Escala para graficar eje x.
        int y_scale=90;                 // Escala para graficar eje y.
        lcd.background(RGB(255,255,255));
        lcd.foreground(Blue);
        lcd.SelectUserFont(BPG_Arial20x20);
        lcd.SetTextCursor(0,0);         // Pongo cursor en posicion
        lcd.cls();
        lcd.puts(">>>>>>>>>>>>>< Proyecto SNOCC ><<<<<<<<<<<<<<\r\n");
        lcd.roundrect( 5,20,470,270,10,8, RGB(255,255,0));          // Rectangulo para encuadre de graficos
        lcd.fillroundrect(10,25,465,264,5,3,  Green);
        lcd.foreground(RGB(255,255,0));
        lcd.background(Green);
           
        for (int n=0;n<Matrix_VCO.vel_max;n++){                     // Recorre x de 0 a vel_max.     
            s = Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[cons_mile_p];  // Consumo por milla del período
            y=int(y_offset-y_scale*s);                              // El consumo máximo es alrededor de 2 l/m => Multiplico por y_scale 
                                                                    // para que ocupe mas pantalla.
            x=n*x_scale+x_offset;                                   // para aumentar el span (eje x)       
            switch (interpolated){ 
            case 0:  if (Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[cons_interpolated]==0){  //Valores sin interpolar
                        lcd.SetTextCursor(x,y-y_text_offset);
                        lcd.printf(".");  
                        }
                    break;
            case 1:  if ((Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[cons_interpolated]==1) || (Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[cons_interpolated]==2))lcd.foreground(Orange); // interpola con puntos de otro color
                        lcd.SetTextCursor(x,y-y_text_offset);   // el offset adicional es para corregir la diferencia de ubicacion linea-caracter.
                        lcd.printf(".");
                        lcd.foreground(RGB(255,255,0));
                    break;
            case 2: lcd.line(x_i,y_i,x,y);  // Imprime linea
                    break;
            default: 
                    lcd.SetTextCursor(x,y-y_text_offset);
                    lcd.printf(".");
                    break;
            }      
                         
        x_i=x;
        y_i=y;
        }
        
        x_i=x_offset;
        y_i=y_offset;
        
        lcd.SelectUserFont(BPG_Arial10x10);     // Seleccion de tipo y tamaño de letras
        lcd.background(Green);
        lcd.foreground(Blue);
        lcd.SetTextCursor(30,32);
        lcd.puts("Cons.(l/m)\r\n");
        lcd.SetTextCursor(420,235);
        lcd.puts("Vel.(kn)\r\n");  
        lcd.line(x_i,y_i,Matrix_VCO.vel_max*x_scale+x_offset,y_i);   // Imprimo eje x.
        for(int j=10;j<=100;j+=10){
            int x=j*x_scale+x_offset;
            lcd.line(x,y_i,x,y_i-5); 
            lcd.SetTextCursor(x,y_i+5);
            lcd.printf("%d",j);
        }              
        lcd.line(x_i,y_i,x_i,40);                           // Imprimo eje y.
            for(int k=1;k<=5;k++){
            y=y_offset-k*0.5*y_scale;
            lcd.line(x_i,y,x_i+10,y); 
            lcd.SetTextCursor(x_i-15,y+5);
            if(y>=0)lcd.printf("%.1f",k*0.5);
            } 
        if (VCO>0){
            s = Matrix_VCO.NAV_DATA[VCO].LAST_NAV_DATA[cons_mile_p];;   // Valor de consumo para VCO.
            y=int(y_offset-y_scale*s);                                  // el consumo máximo es alrededor de 2 l/m. Multiplico por y_scale para que ocupe mas pantalla.
            x=VCO*x_scale+x_offset;                                     // para aumentar el span (eje x)
            if (interpolated==2){
                lcd.circle(x,y,5); 
            }                                        
            else{
                lcd.SetTextCursor(x,y);         
                lcd.printf("*");
            } 
            lcd.SetTextCursor(VCO*x_scale+x_offset+10,y_offset-s*y_scale+20);
            lcd.printf("%f l/m",s);              
            lcd.SetTextCursor(VCO*x_scale+x_offset+10,y_offset-s*y_scale+40);
            lcd.printf("VCO: %d kn",VCO);  

        }
        else{
            lcd.SetTextCursor(120,35); 
            lcd.SelectUserFont(BPG_Arial10x10);     // Seleccion de tipo y tamaño de letras        
            lcd.printf("No hay datos suficientes para obtener la VCO");
            lcd.printf("%d",VCO);//DEBUG
        }
        lcd.foreground(RGB(255,255,0));
        lcd.background(Black);
    }
    
    
 /* Funcion  print_VCO_data : Imprime una tabla con los datos de consumo/milla en funcion de la velocidad a partir del vector de objetos NAV_DATA de la clase VCODATA, con lineas (printline=1) o puntos (=0)
    Parametros: Objeto VCODATA; */

    void print_VCO_data(VCODATA &Matrix_VCO){
            float cons, vel;
            lcd.SelectUserFont(BPG_Arial10x10);     // Seleccion de tipo y tamaño de letras
            lcd.background(RGB(255,255,255));
            lcd.foreground(Blue);
            lcd.SetTextCursor(0,0);                 // Pongo cursor en posicion
            lcd.cls();
            lcd.puts("Velocidad-Consumo\r\n");
            for (int n=0;n<83;n++){                                     // Recorre x de 0 a 83. (Maxima cantidad que entra en una pantalla)    
            cons = Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[cons_mile_p];   // Consumo por milla del período
            vel= Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[speed_p];         // Velocidad del período.
            lcd.printf("|  %d - %f  |  %f  |",n,vel,cons);
            } 
            wait(3);
            lcd.cls();
            for (int n=83;n<Matrix_VCO.vel_max;n++){                     // Recorre x de 0 a vel_max.     
            cons = Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[cons_mile_p];   // Consumo por milla del período
            vel= Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[speed_p];         // Velocidad del período.
            lcd.printf("|  %d - %f  |  %f  |",n,vel,cons);
            }                                       
            //lcd.SelectUserFont(BPG_Arial20x20);     // Seleccion de tipo y tamaño de letras
    
    }
    
    
/* Funcion mtrx2sd: Guarda los datos de la matriz en un archivo de texto existente*/
    
    int mtrx2sd(VCODATA &Matrix_VCO, const char *filename){
            float lngtd_f,lngtd_i,lttd_f,lttd_i,tm_f,tm_i,dstnc_p,spd_p,cnsmptn_i,cnsmptn_f,cnsmptn_p,cns_ml_p,cns_hr_p,cns_ntrpltd; // Variables de navegacion;
            FILE *fp1;
            fp1 = fopen(filename, "w");   //Apertura para escritura
            if(fp1 == NULL) {
            //error("Could not open file for write\n");
            return -1;
            }       
            for (int n=0;n<Matrix_VCO.vel_max;n++){
                //cons = Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[cons_mile_p];   // Consumo por milla del período
                //vel= Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[speed_p];         // Velocidad del período.
                
                lngtd_f= Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[longitude_f];        // Longitud y Latitud iniciales y finales.
                lngtd_i= Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[longitude_i];
                lttd_f= Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[latitude_f];
                lttd_i= Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[latitude_i];
                tm_f= Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[time_f];                  // El dato (timestamp al final del período en cuestion, en horas) se obtendrá luego proveniente del GPS.
                tm_i= Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[time_i];                  // Timestamp al inicio del período en horas.
                dstnc_p= Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[distance_p];          // Distancia recorrida durante este período en millas nauticas.
                spd_p= Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[speed_p];                // Velocidad media del período en nudos.
                cnsmptn_i= Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[consumption_i];    // Consumo en litros al comienzo del período.
                cnsmptn_f= Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[consumption_f];    // Consumo en litros al final del período.
                cnsmptn_p= Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[consumption_p];    // Consumo en litros del período.
                cns_ml_p= Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[cons_mile_p];        // Consumo en litros por milla nautica.
                cns_hr_p= Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[cons_hour_p];        // Consumo en litros por hora.
                cns_ntrpltd= Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[cons_interpolated];  // Consumo interpolado?: -1-> initial padding
                
                
                fprintf(fp1,"%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f\r\n",lngtd_f,lngtd_i,lttd_f,lttd_i,tm_f,tm_i,dstnc_p,spd_p,cnsmptn_i,cnsmptn_f,cnsmptn_p,cns_ml_p,cns_hr_p,cns_ntrpltd);
                }
           return fclose(fp1);
           }
           
/* Funcion sd2mtrx: Guarda los datos de un archivo de texto existente en la matriz*/           
           
    int sd2mtrx(VCODATA &Matrix_VCO, const char *filename){  
        float lngtd_f,lngtd_i,lttd_f,lttd_i,tm_f,tm_i,dstnc_p,spd_p,cnsmptn_i,cnsmptn_f,cnsmptn_p,cns_ml_p,cns_hr_p,cns_ntrpltd; // Variables de navegacion;  
        FILE *fp1;
        fp1 = fopen(filename, "r");   //Apertura para escritura
        if(fp1 == NULL) {
            //error("Could not open file for read\n");
            return -1;
            }
        for (int n=0;n<Matrix_VCO.vel_max;n++){
            fscanf(fp1,"%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f",&lngtd_f,&lngtd_i,&lttd_f,&lttd_i,&tm_f,&tm_i,&dstnc_p,&spd_p,&cnsmptn_i,&cnsmptn_f,&cnsmptn_p,&cns_ml_p,&cns_hr_p,&cns_ntrpltd);                 // Leemos un float y lo guardamos
            Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[longitude_f]=lngtd_f;
            Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[longitude_i]=lngtd_i;
            Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[latitude_f]=lttd_f;
            Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[latitude_i]=lttd_i;
            Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[time_f]=tm_f;
            Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[time_i]=tm_i;
            Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[distance_p]=dstnc_p;
            Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[speed_p]=spd_p;
            Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[consumption_i]=cnsmptn_i;
            Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[consumption_f]=cnsmptn_f; 
            Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[consumption_p]=cnsmptn_p;
            Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[cons_mile_p]=cns_ml_p;
            Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[cons_hour_p]=cns_hr_p;
            Matrix_VCO.NAV_DATA[n].LAST_NAV_DATA[cons_interpolated]=cns_ntrpltd;  

        }               
        return fclose(fp1);   
        }
           
/* Funcion build_default_Mtrx: Carga los datos (consumo/milla) del vector LAST_NAV_DATA de los objetos NAVDATA de VCODATA para testing.*/

void   build_default_Mtrx(VCODATA &Test_Matrix_VCO){
     
        NAVDATA TestNDO;
 
        TestNDO.LAST_NAV_DATA[cons_interpolated]=-1;
        
        TestNDO.LAST_NAV_DATA[cons_mile_p]=0.3;   // 15-->0.3 ; 16-->0.2; 17-->0.35; 30-->0.1; 32-->0.15; 34-->0.12; 99-->0.25
        TestNDO.LAST_NAV_DATA[speed_p]=15;
        Test_Matrix_VCO.store_data(TestNDO);
        Test_Matrix_VCO.store_data(TestNDO);
        TestNDO.LAST_NAV_DATA[cons_mile_p]=0.2;
        TestNDO.LAST_NAV_DATA[speed_p]=16;
        Test_Matrix_VCO.store_data(TestNDO);
        Test_Matrix_VCO.store_data(TestNDO);
        TestNDO.LAST_NAV_DATA[cons_mile_p]=0.35;
        TestNDO.LAST_NAV_DATA[speed_p]=17;
        Test_Matrix_VCO.store_data(TestNDO);
        Test_Matrix_VCO.store_data(TestNDO);
        TestNDO.LAST_NAV_DATA[cons_mile_p]=0.1;
        TestNDO.LAST_NAV_DATA[speed_p]=30;
        Test_Matrix_VCO.store_data(TestNDO);
        Test_Matrix_VCO.store_data(TestNDO);
        TestNDO.LAST_NAV_DATA[cons_mile_p]=0.15;
        TestNDO.LAST_NAV_DATA[speed_p]=32;
        Test_Matrix_VCO.store_data(TestNDO);
        Test_Matrix_VCO.store_data(TestNDO);       
        TestNDO.LAST_NAV_DATA[cons_mile_p]=0.12;
        TestNDO.LAST_NAV_DATA[speed_p]=34;
        Test_Matrix_VCO.store_data(TestNDO);
        Test_Matrix_VCO.store_data(TestNDO);
        TestNDO.LAST_NAV_DATA[cons_mile_p]=0.25;
        TestNDO.LAST_NAV_DATA[speed_p]=(Test_Matrix_VCO.vel_max)-1;
        Test_Matrix_VCO.store_data(TestNDO);
        Test_Matrix_VCO.store_data(TestNDO);
        Test_Matrix_VCO.interpolate(); 
       
       /*for (int i=0;i<30;i++){
        TestNDO.LAST_NAV_DATA[cons_mile_p]=i+1;
        TestNDO.LAST_NAV_DATA[speed_p]=i;
        Test_Matrix_VCO.store_data(TestNDO);
        }
        for (int i=30,x=30;i>1;i--,x++){
        TestNDO.LAST_NAV_DATA[cons_mile_p]=i;
        TestNDO.LAST_NAV_DATA[speed_p]=x;
        Test_Matrix_VCO.store_data(TestNDO);
        }
        TestNDO.LAST_NAV_DATA[cons_mile_p]=1;
        TestNDO.LAST_NAV_DATA[speed_p]=55;
        Test_Matrix_VCO.store_data(TestNDO);
        for (int i=1,x=59;i<40;i++,x++){
        TestNDO.LAST_NAV_DATA[cons_mile_p]=i+1;
        TestNDO.LAST_NAV_DATA[speed_p]=x;
        Test_Matrix_VCO.store_data(TestNDO);
        }*/
     }   

    
int main()
{
    pc.baud(460800);                                           // I like a snappy terminal, so crank it up!
    pc.printf("\r\nRA8875 Soft Fonts - Build " __DATE__ " " __TIME__ "\r\n");
    lcd.init();
    lcd.TouchPanelCalibrate("Calibrate the touch panel");   // 4 touch
    lcd.cls();
    rect_t PrintScreenRect = { 425-65, 20, 425+65, 60};     // Rectangulo para encuadrar boton.
    lcd.foreground(RGB(255,255,0));                         // Seteo del color de las letras.
    lcd.SelectUserFont(BPG_Arial20x20);                     // Seleccion de tipo y tamaño de letras
    GPS gps(p9, p10);                                       // Agrego para comunicacion con el GPS
    

//-------------------------------------------------------------------------------------------------------------         
//      Sensor de flujo:       

    InterruptIn pulse_sensor(p15);          // Defino pulse_sensor como una entrada de interrupción en p15 .
    pulse_sensor.mode(PullUp);              // PullUp para esa entrada.
    //DigitalOut led(LED1);
    //pulse_sensor.rise(&trigger);          // Dispara interrupción con flanco ascendente. (Podría tambien ser desecendente--> fall)
    pulse_sensor.fall(&trigger); 
 
 //--------------------------------------------------------------------------------------------------------------           
    lcd.SetTextCursor(0,0);                 // Posicionamiento de cursor.
    lcd.puts(">>>>>>>>>>>>>< Proyecto SNOCC ><<<<<<<<<<<<<<\r\n");
    
    if (!sd2mtrx(NAVIGATION_VMATRIX, sd_file)) lcd.puts("Datos leidos de SD card\r\n");                       // Cargo matriz desde SD.
    else{
        lcd.puts("Error al leer los datos.\r\n Inicio sin datos historicos.\r\n");
        lcd.printf("Creando directorio en SD card...\r\n");
        if(!mkdir(sd_dir, 0777)){                                                                               // Creo directorio si no existe.
        lcd.printf("Creado:  %s\r\n", sd_dir);
        lcd.printf("Cargando datos de inicio default en SD card...\r\n");
        build_default_Mtrx(NAVIGATION_VMATRIX);                                                                 // Creando matriz de inicio default.
        if (!mtrx2sd(NAVIGATION_VMATRIX, sd_file)) lcd.printf("Datos default guardados en SD card\r\n");
        else lcd.puts("Error al guardar los datos default.\r\nNo se podran almacenar los datos.\r\n");
        }
        else lcd.puts("Error al crear directorio en SD card. No se podran almacenar los datos.\r\n");
        } 
    wait(3);
       
              
       
    while(1) {
            
        lcd.SetTextCursor(0,0);             // Pongo cursor en posicion
        lcd.puts(">>>>>>>>>>>>>< Proyecto SNOCC ><<<<<<<<<<<<<<\r\n");
        //lcd.printf("M0: %s \r\n\r\n", gps.msg);  //Imprimo el mensaje crudo proveniente de la uart
         
        if(gps.sample()) {             // Si es exitosa la obtencion de datos del gps.
            poll_init=1;               
            lcd.cls();
            lcd.foreground(RGB(255,255,0));     // Seteo del color de las letras.
            lcd.SelectUserFont(BPG_Arial20x20);     // Seleccion de tipo y tamaño de letras
            lcd.SetTextCursor(0,0);                      // Pongo cursor en posicion
            lcd.puts(">>>>>>>>>>>>>< Proyecto SNOCC ><<<<<<<<<<<<<<\r\n");
            
            if (NAVIGATION_TABLE.rotate_data(gps.longitude, gps.latitude, gps.time, Counter)){
            NAVIGATION_VMATRIX.store_data(NAVIGATION_TABLE);// Luego de rotar los datos en la tabla de navegacion, la guarda en la matriz segun criterios de la clase VCODATA                                                                
            lcd.puts("Rotacion exitosa!-->");
            int i=int(NAVIGATION_TABLE.LAST_NAV_DATA[speed_p]);   
            int VCO=NAVIGATION_VMATRIX.get_VCO();
            float timetick_f_Last = NAVIGATION_TABLE.LAST_NAV_DATA[speed_p];                        // DEBUG
            float timetick_f_Mtrx = NAVIGATION_VMATRIX.NAV_DATA[i].LAST_NAV_DATA[time_f];           // DEBUG
            float distance_p_Mtrx = NAVIGATION_VMATRIX.NAV_DATA[i].LAST_NAV_DATA[distance_p];       // DEBUG
            float speed_p_Mtrx = NAVIGATION_VMATRIX.NAV_DATA[i].LAST_NAV_DATA[speed_p];             // DEBUG
            float speed_p_Last = NAVIGATION_TABLE.LAST_NAV_DATA[speed_p];                           // DEBUG
            float longitude_f_Mtrx = NAVIGATION_VMATRIX.NAV_DATA[i].LAST_NAV_DATA[longitude_f];     // DEBUG
            float latitude_f_Mtrx = NAVIGATION_VMATRIX.NAV_DATA[i].LAST_NAV_DATA[latitude_f];       // DEBUG
            float cons_hour_p_Mtrx = NAVIGATION_VMATRIX.NAV_DATA[i].LAST_NAV_DATA[cons_hour_p];
            float cons_mile_p_Mtrx = NAVIGATION_VMATRIX.NAV_DATA[i].LAST_NAV_DATA[cons_mile_p];
            lcd.printf("INDICE_Mtrx: %d\r\n",i);                            // DEBUG
            lcd.printf("Speed_f_Mtrx(%d):     %f kn.\r\n",i, speed_p_Mtrx);                             // DEBUG
            lcd.printf("Speed_f_Last(%d):     %f km/h.\r\n",i, speed_p_Last*1.852);                     // DEBUG
            lcd.printf("Time_f_Mtrx(%d):      %f Hours.\r\n",i, timetick_f_Mtrx);                        // DEBUG
            lcd.printf("Time_f_Last(%d):      %f Hours.\r\n",i, timetick_f_Last);                        // DEBUG
            lcd.printf("Dist_p_Mtrx(%d):      %f miles.\r\n",i,distance_p_Mtrx);                     // DEBUG
            lcd.printf("Posicion: Long(%d):   %f    ; Lat:     %f\r\n",i,longitude_f_Mtrx,latitude_f_Mtrx);   // DEBUG
            lcd.printf("FlujoVCOmtrx(%d):     %f Litros/Hora\r\n",i, cons_hour_p_Mtrx);                 // DEBUG
            lcd.printf("FlujoVCOmtrx(%d):     %f Litros/Milla\r\n",i, cons_mile_p_Mtrx);                 // DEBUG
            lcd.printf("Cons. Acumulado:      %f l\r\n", LCounter);
            lcd.printf("VCO:                      %d km/h\r\n", VCO); 
            

            NAVIGATION_VMATRIX.interpolate();                                                              // Interpolacion.
            if (!mtrx2sd(NAVIGATION_VMATRIX, sd_file)) lcd.printf("Datos guardados en SD card\r\n");       // Almacenamiento de datos en SD.
            else lcd.printf("Error al guardar los datos.\r\n");
           
            //build_default_Mtrx(NAVIGATION_VMATRIX);    // DEBUG Curve
            //print_VCO_curve(NAVIGATION_VMATRIX,1);
            }
            else lcd.puts("Periodo no valido!\r\n");  
           
            } 
            else {
            lcd.background(Black);
            lcd.cls();
            lcd.foreground(RGB(255,255,0));             // Seteo del color de las letras.
            lcd.SelectUserFont(BPG_Arial20x20);         // Seleccion de tipo y tamaño de letras
            lcd.SetTextCursor(0,0);                     // Posicionamiento de cursor.
            lcd.puts(">>>>>>>>>>>>>< Proyecto SNOCC ><<<<<<<<<<<<<<\r\n");
            lcd.SetTextCursor(0,100);    
            

    if (!mtrx2sd(NAVIGATION_VMATRIX, sd_file)) lcd.printf("Datos guardados en SD card\r\n");
    else lcd.printf("Error al guardar los datos.\r\n");
            
            lcd.printf("Aun no hay datos disponibles :(\r\n");
            lcd.SetTextCursor(0,180);
            lcd.printf("Timetick %f h\r\n", NAVIGATION_TABLE.LAST_NAV_DATA[time_f]); 
            lcd.printf("Flujo Mtrx: %f Litros/Hora\r\n", NAVIGATION_TABLE.LAST_NAV_DATA[cons_hour_p]);
            lcd.printf("Flujo Counter: %f Litros\r\n", LCounter);                
               
            //if (poll_init==0) build_default_Mtrx(NAVIGATION_VMATRIX);     //DEBUG
               
               }
                         
           for (int i=0;i<200;i++) {                 // Barrido para el touch
            point_t p;
            lcd.fillrect(PrintScreenRect, Green);
            lcd.foreground(Blue);
            lcd.background(Green);
            lcd.puts(425-60, 22, "GET CURVE");
            lcd.background(Black);
            //wait_us(1);
            if (lcd.TouchPanelReadable(&p)) {
            //lcd.foreground(Blue);
            //lcd.SetTextCursor(10, 15);
            //lcd.printf("(%3d,%3d)", p.x, p.y);
            //lcd.foreground(RGB(255,255,0));
            
            if (Intersect(PrintScreenRect, p)) {
            lcd.foreground(Red);
            lcd.puts(400-38, 20, "GET CURVE");
            //build_default_Mtrx(NAVIGATION_VMATRIX);    // DEBUG Curve
            NAVIGATION_V_SMOOTH_MTRX.smooth(4, NAVIGATION_VMATRIX); // Genera matriz de datos filtrados con pasabajos
            //lcd.puts(425-120, 22, "ANTES de PRINT");                     //DEBUG
            print_VCO_curve(NAVIGATION_VMATRIX,0);                  // Valores recolectados
            wait(2);
            print_VCO_curve(NAVIGATION_VMATRIX,1);                  // Interpolados (puntos)
            wait(3);
            print_VCO_curve(NAVIGATION_V_SMOOTH_MTRX,1);            // Suavizado (puntos)
            wait(3);
        
            print_VCO_curve(NAVIGATION_VMATRIX,2);                  // Interpolados (lineas)
            wait(3);
            print_VCO_curve(NAVIGATION_V_SMOOTH_MTRX,2);            // Suavizados (lineas)
            wait(3);
            print_VCO_data(NAVIGATION_VMATRIX);                     // Volcado de datos
            wait(4);
            break;
                //GetScreenCapture();
            }
            
           }
             lcd.foreground(RGB(255,255,0));
        }
    }
    }