// DSPIC33FJ256GP710 Configuration Bit Settings

// 'C' source line config statements

// FBS
#pragma config BWRP = WRPROTECT_OFF     // Boot Segment Write Protect (Boot Segment may be written)
#pragma config BSS = NO_FLASH           // Boot Segment Program Flash Code Protection (No Boot program Flash segment)
#pragma config RBS = NO_RAM             // Boot Segment RAM Protection (No Boot RAM)

// FSS
#pragma config SWRP = WRPROTECT_OFF     // Secure Segment Program Write Protect (Secure Segment may be written)
#pragma config SSS = NO_FLASH           // Secure Segment Program Flash Code Protection (No Secure Segment)
#pragma config RSS = NO_RAM             // Secure Segment Data RAM Protection (No Secure RAM)

// FGS
#pragma config GWRP = OFF               // General Code Segment Write Protect (User program memory is not write-protected)
#pragma config GSS = OFF                // General Segment Code Protection (User program memory is not code-protected)

// FOSCSEL
#pragma config FNOSC = PRIPLL           // Oscillator Mode (Primary Oscillator (XT, HS, EC) w/ PLL)
#pragma config IESO = ON                // Two-speed Oscillator Start-Up Enable (Start up with FRC, then switch)

// FOSC
#pragma config POSCMD = NONE            // Primary Oscillator Source (Primary Oscillator Disabled)
#pragma config OSCIOFNC = OFF           // OSC2 Pin Function (OSC2 pin has clock out function)
#pragma config FCKSM = CSDCMD           // Clock Switching and Monitor (Both Clock Switching and Fail-Safe Clock Monitor are disabled)

// FWDT
#pragma config WDTPOST = PS32768        // Watchdog Timer Postscaler (1:32,768)
#pragma config WDTPRE = PR128           // WDT Prescaler (1:128)
#pragma config WINDIS = OFF             // Watchdog Timer Window (Watchdog Timer in Non-Window mode)
#pragma config FWDTEN = ON              // Watchdog Timer Enable (Watchdog timer always enabled)

// FPOR
#pragma config FPWRT = PWR128           // POR Timer Value (128ms)

// FICD
#pragma config ICS = PGD1               // Comm Channel Select (Communicate on PGC1/EMUC1 and PGD1/EMUD1)
#pragma config JTAGEN = OFF             // JTAG Port Enable (JTAG is Disabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

/*******librerias******************/
#include "xc.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "p33FJ256GP710.h" 
#include "dsp.h"

/**********************************/


/**********************************/
#define Fcy 40000000
#define delay_ms(x) __delay32((Fcy/1000)*x) //delay en milisegundos
#define FFT_BLOCK_LENGTH 256
#define M_PI 3.14159265358979323846 /* pi */


/**********************************/
/*DECLARACION DE FUNCIONES*/
void Configurar_UART();
void Configurar_IO();
void OscConfig();
void ADC_Data();
void ADCStart();
void ADCInit();
void Serial_SendString(char *str);
void Serial_PutChar(char Ch);
void Configurar_Timer32();



/**************************/
float temp1 = 0;
unsigned long int temp;
char Salto[] = "\n";
char trama[5];
unsigned long int gcont = 0;
float fase = 0;
float denom = 0;
float numer = 0;
int chiv = 0;
int chiv2 = 0;
int timer2 = 0;
int timer3 = 0;
int timer22 = 0;
int timer33 = 0;
int cont = 0;
int i = 0;
int cant = 0;
int t3serie = 0;
int t2serie = 0;
float vector1[4];
float vector2[4];
float var1, var2, var3, var4;
signed int imaginario[4] = {0, -1, 0, 1};
signed int real [4] = {1, 0, -1, 0};

void __attribute__((__interrupt__, __auto_psv__)) _T3Interrupt(void) {
    _T3IF = 0; /* Ponemos a 0 el Flag de la Int del Timer 1 */
}

void __attribute__((__interrupt__, no_auto_psv)) _U2RXInterrupt(void) {
    U2TXREG = U2RXREG; //se trasmite lo que se recibe
    _U2RXIF = 0; // Borramos flag.
}

void __attribute__((interrupt, no_auto_psv)) _ADC1Interrupt() {
    temp = ADCBUF0;
    temp1 = temp;
    temp1 = (temp1 * (3.313)) / 1023.0;
    vector1[cont] = temp1;
    cont++;
    //    sprintf(trama, "%.4f", (double) temp1);
    //    Serial_SendString(trama);
    //    Serial_SendString(Salto);
    if (chiv2 == 1) {
        chiv2 = 0;
        sprintf(trama, "%.4f", (double) fase);
        Serial_SendString(trama);
        Serial_SendString(Salto);
    }
    if (cont == 4) {
        chiv = 1;
    }
    IFS0bits.AD1IF = 0; // Reseteamos el Flag del ADC
}

int main(void) {
    OscConfig();
    cont = 0;
    chiv = 0;
    Configurar_IO();
    ADCInit(); // Inicializamos el conversor A/D
    Configurar_UART();
    Configurar_Timer32();
    while (OSCCONbits.LOCK != 1);
    ADCStart(); // Encendemos el ADC
    T2CONbits.TON = 1;
    while (1) {
        if (chiv == 1) {
            cont = 0;
            //            sprintf(trama, "%.4f", (double) temp1);
            //            Serial_SendString(trama);
            //            Serial_SendString(Salto);
            for (i = 0; i <= 3; i++) {
                vector2[i] = vector1[i];
                //                            sprintf(trama, "%.4f", (double) vector2[i]);
                //                            Serial_SendString(trama);
                //                            Serial_SendString(Salto);
            }
            denom = vector2[0] - vector2[2];
            numer = vector2[3] - vector2[1];
            fase = (atan(numer / denom))*(180 / M_PI);
            chiv2 = 1;
        }
        //        if (chiv == 1) {
        //            for (i = 0; i <= 4; i++) {
        //                vector2[i] = vector1[i];
        //            }
        //            chiv = 0;
        //            cont = 0;
        //            denom = vector2[0] - vector2[2];
        //            numer = vector2[3] - vector2[1];
        //            fase = (atan(numer / denom))*(180 / M_PI);
        //            for (i = 0; i <= 3; i++) {
        //                sprintf(trama, "%.4f//", (double) vector2[i]);
        //                Serial_SendString(trama);
        //            }
        //            sprintf(trama, "%.4f:", (double) numer);
        //            Serial_SendString(trama);
        //            sprintf(trama, "%.4f::", (double) denom);
        //            Serial_SendString(trama);
        //            sprintf(trama, "%.4f", (double) fase);
        //            Serial_SendString(trama);
        //            Serial_SendString(Salto);
        //            //delay_ms(1000);
        //        }
        //        while (!IFS0bits.AD1IF);
        //        IFS0bits.AD1IF = 0;
        //        ADC_Data();
        //        temp1 = (temp1 * (3.313)) / 1023.0;
        //        vector[cont] = temp1;
        //        //        switch (cont) {
        //        //            case 1: var1 = temp1;
        //        //                break;
        //        //            case 2: var2 = temp1;
        //        //                break;
        //        //            case 3: var3 = temp1;
        //        //                break;
        //        //            case 4: var4 = temp1;
        //        //        }
        //        cont++;
        //        if (cont == 4) {
        //            cont = 0;
        //            denom = vector[0] - vector[2];
        //            numer = vector[3] - vector[1];
        //            ;
        //            fase = (atan(numer / denom))*(180 / M_PI);
        //            for (i = 0; i <= 3; i++) {
        //                sprintf(trama, "%.4f//", (double) vector[i]);
        //                Serial_SendString(trama);
        //            }
        //
        //            //            sprintf(trama, "%.4f//", (double) var1);
        //            //            Serial_SendString(trama);
        //            //            sprintf(trama, "%.4f//", (double) var2);
        //            //            Serial_SendString(trama);
        //            //            sprintf(trama, "%.4f//", (double) var3);
        //            //            Serial_SendString(trama);
        //            //            sprintf(trama, "%.4f//", (double) var4);
        //            //            Serial_SendString(trama);
        //            sprintf(trama, "%.4f:", (double) numer);
        //            Serial_SendString(trama);
        //            sprintf(trama, "%.4f::", (double) denom);
        //            Serial_SendString(trama);
        //            sprintf(trama, "%.4f", (double) fase);
        //            Serial_SendString(trama);
        //            Serial_SendString(Salto);
        //            //delay_ms(1000);
        //        }
    }
    return 0;
}

void Configurar_UART() {//uart 1
    U2MODEbits.BRGH = 1;
    U2MODEbits.PDSEL = 0b00; // No Parity, 8 data bits
    U2MODEbits.STSEL = 0; // 1 Stop bit    
    U2MODEbits.UEN = 0b00;
    U2MODEbits.ABAUD = 0; // Auto-Baud Disabled    
    U2BRG = 9;
    U2STAbits.URXISEL = 0; // Interrupt after one RX character is received
    IFS1bits.U2RXIF = 0; // Clear the Recieve Interrupt Flag
    IEC1bits.U2RXIE = 1; // Enable Recieve Interrupts
    U2MODEbits.UARTEN = 1; // Enable UART
    U2STAbits.UTXEN = 1; // Enable UART TX
}

void Configurar_IO() {
    TRISB = 0; /*	Puerto B como salida */
    TRISF = 0xFFF7;
}
// Send a string out to the serial interface.

void OscConfig() {
    //CONFIGURACION PARA OBTENER UNA Fcy=40MHz
    //Fosc = Fin * M/(N1*N2), Fcy = Fosc/2
    //Fosc = 20MHz * 16/(2*2) = 80MHz para una entrada de reloj de 20MHz
    CLKDIV = 0x0000; // N1=2 Y N2=2
    PLLFBD = 0x000E; // M=16
    OSCTUN = 0; // Desactivar afinado del oscilador FRC, si está activo
    RCONbits.SWDTEN = 0; //Desactivar Watch Dog Timer
}

void ADCInit() {
    AD1PCFGLbits.PCFG10 = 0; // Se configura el ADPCFG para que el único pin 
    // usado analógicamente sea el AN10
    AD1CON1bits.SSRC = 0b111; // selección de la muestra después que la conversión termina
    AD1CON1bits.ASAM = 1; // Formato del resultado entero, Comienzo de la conversión automático, 
    AD1CON1bits.AD12B = 0; //10 bits resolución
    AD1CHS0bits.CH0SA = 0b1010; //  Entrada positiva AN10 para la entrada de la muestra
    AD1CHS0bits.CH0NA = 0; // Entrada negativa se usa el VR-
    AD1CON2bits.VCFG = 0b000; // Referencias: AVDD y AVSS,
    AD1CON2bits.BUFM = 0; //Se selecciona nivel de buffer 16*1 y 
    AD1CON3bits.ADCS = 11;
    IFS0bits.AD1IF = 0; // Reseteamos el Flag del ADC
    IEC0bits.AD1IE = 1; // Habilitamos la Interrupción	
}

void ADCStart() {
    AD1CON1bits.ADON = 1; // Prende el ADC
}

void ADC_Data() {
    unsigned long int temp;
    temp = ADCBUF0;
    temp1 = temp;
}

void Serial_PutChar(char Ch) { // wait for empty buffer 
    while (U2STAbits.UTXBF == 1);
    U2TXREG = Ch;
}

// Send a string out to the serial interface.

void Serial_SendString(char *str) {
    char * p;
    p = str;
    while (*p)
        Serial_PutChar(*p++);
}

void Configurar_Timer32() {
    T3CONbits.TON = 0;
    T2CONbits.TON = 0;
    T2CONbits.T32 = 1;
    T2CONbits.TCS = 0;
    T2CONbits.TGATE = 0;
    T2CONbits.TCKPS = 0b11;
    TMR3 = 0;
    TMR2 = 0;
    PR3 = 0xFFFF;
    PR2 = 0xFFFF;
    IPC2bits.T3IP = 1;
    IFS0bits.T3IF = 0;
    IEC0bits.T3IE = 0;
}

